ES6이다 뭐다... 모든브라우저에서 작성한 코드가 동작을 안하는 경우 난감한 상황이 발생 할 수 있다.

그중에 하나가 javascript 작성시 중복제거 코드를 작성했는데 IE에서 동작하지 않는 경우를 볼 수 있다.

 

findindex나 화살표함수(ES6) 문법을 사용하는 코드의 경우 문제가 될 수 있다.

아직까지 IE가 사라지지 않았으므로.. jQuery를 이용한 중복제거 함수를 작성해 보았다.

1
2
3
4
5
6
7
8
9
var valueArr = ["11","22","33","44","11","55","66"]; // 원본배열
var uniqueArr = []; // 중복이 제거된 배열이 생성될 변수
$.each(valueArr, function(k, val){ 
    if($.inArray(val, uniqueArr) === -1){
        uniqueArr.push(val); 
    }
});
 
console.log(uniqueArr);
cs

 

관리자 계정명 관리

 

관리자 계정명 미변경 및 기본유저 로그인 가능할 시 취약하다.

관리자 콘솔 사용시 User name 확인
[4.x / 5.x] - /[Tomcat path]/conf/tomcat-users.xml

 

<tomcat-users> 
<role rolename=""tomcat""/>
  <role rolename=""admin-gui""/>
  <role rolename=""manager-gui""/>
  <role rolename=""role1""/>
  <user username=""autoever"" password=""autoever"" roles=""admin-gui,manager-gui""/>
  <user username=""tomcat"" password=""tomcat"" roles=""tomcat""/>
  <user username=""both"" password=""tomcat"" roles=""tomcat,role1""/>
  <user username=""role1"" password=""tomcat"" roles=""role1""/> </tomcat-users>

[6.x / 7.x / 9.x] - /[tomcat path]/conf/tomcat-users.xml

 

(apt-get 으로 설치한 경우 /etc/tomcat7/tomcat-users.xml에 있을 수 있음)

 

[시스템현황] [ tomcat dir ]\conf\tomcat-users.xml 'tomcat-user' 설정 미존재

 

 

조치사항

 

1. [4.x / 5.x] - 관리자 콘솔 사용시 User name 확인 및 변경

   [6.x / 7.x] – 아래의 설정 파일을 통해 User name 확인 및 변경 설정 파일 : /[Tomcat path]/conf/tomcat-users.xml

 

2. [4.x / 5.x] - 관리자 콘솔의 [User Definition | Users | RoleName]에서 계정명을 설정

 

3. [6.x / 7.x] - 기본 유저와 패스워드를 삭제 또는 주석으로 처리해 주어 기본 유저로의 로그인이 불가능 하도록 권고한다.

 

설정 파일 : /[Tomcat path]/conf/tomcat-users.xml

관리자 콘솔 관리

Default 포트(8080)를 사용하고 있고, 관리자 콘솔 사용시 취약하다.

Tomcat 관리자 콘솔 사용 유무 확인함.
예) http://[Domain]/manager, http://[Domain]/admin/

(단, Tomcat 5.5.x의 버전의 경우 admin을 따로 다운로드 받아 설치하여야 하며
6.0 이상의 버전엔 http://[Domain]/admin/ 자체가 존제하지 않으므로 http://[Domain]/manager 만 확인)

 

 

조치사항

1. Default포트인 8080은 공격자가 유추 할 수 있으므로, 유추할 수 없는 포트로 변경. 번호를 지정하여 사용하기를 권고함 (권장 포트 범위 : 1024~65534)

 

    - 설정 파일 : /[Tomcat path]/conf/server.xml

    - server.xml 파일 변경 후 Tomcat 서버를 Stop하고 다시 start 시켜야 적용됨


2. 필요 시에만 관리자 콘솔 운영을 권고함, 필요한 경우에 한하여 관리자 콘솔을 사용하고 불필요한 경우 프로세스를 종

 

지난 시간에 이어서 자식/형제요소 및 조합 선택자를 알아보도록 하겠습니다.

 

  • 자식요소 선택자 ( > )

selector로 하나의 요소를 지정한 후 > 선택자를 사용하여 자식요소를 지정할 수 있습니다.  1개의 자식요소가 선택되어 집니다. 

$("#myObject > div");

 

  • 자식요소 선택자(복수)

selector로 하나의 요소를 지정한 후 띄워쓰기 후 해당 선택요소를 지정합니다.

$("#myObject div");

$("#myObject div").eq(0); // div tag 요소 중 첫번째 자식요소

 

  • 형제요소 선택자

지정된 myObject 요소의 형제요소를 선택할때 사용 할 수 있습니다. 

$('#myObject + div'); // #myObject 바로 다음 div를 선택합니다.


$('#myObject ~ div'); // #myObject 형제 div를 모두 선택합니다.
$('#myObject ~ div').eq(1);

 

  • 조합 선택자

지난 시간 및 위에 소개된 선택자를 복합적으로 사용하여 요소를 지정할 수 있습니다. 

 

아래의 구성요소중 span #2를 찾을 경우 

<div id="myObject">
	<div> 1번 div </div>
    <div> 2번 div </div>
    <div> 
    	<span> span #1 </span>
        <span> span #2 </span>
    </div>
</div>

다음과 같이 구성하여 요소를 선택 할 수 있습니다. 

$("#myObject div span").eq(1)

 

jQuery에 대해서 업무 중 교육을 할 일이 생겨 정리합니다.

 

  • jQuery를 왜 사용하는 것인가?

   jQuery는 Selector가 없다면 사용을 안 할 수도 있다 라는 생각이 될 정도로 편리한 Selector를 제공합니다. 

   CSS 선택자를 그대로 사용할 수 있어 코드 선택이 매우 간단합니다. 물론 document.querySelector   

   와 document.querySelectorAll이 있기도 하지만 모르는 사람이 더 많을뿐더러 이미 jQuery가 자리 잡은 상황이기

   때문에 jQuery가 개발하는 사람들에게는 더 친숙합니다. 

 

 

 

 

jQuery Selector를 사용함에 있어 몇 가지만 알아도 사용하는 데에는 큰 무리가 없습니다. 

 

 

  • Id로 해당 Object 찾기(#)

단순히 #뒤에 아이디를 입력하여 해당 오브젝트를 선택할 수 있습니다.

//javascript
document.getElementById('objId');

//jQuery
$('#objId');

 

 

  • class로 Object 찾기(.)|

단순히. 뒤에 해당 css class 명을 입력하여 해당 오브젝트를 선택할 수 있습니다. 이때 동일한 class가 여러 개인 경우

. eq(숫자)를 이용하여 해당 인덱스에 해당하는 오브젝트를 선택할 수 있습니다.

 

//javascript
document.getElementsByClassName('your_class_name');

//jQuery
$('.your_class_name');

// 4번째 오브젝트 선택 (0부터 시작)
$('.your_class_name').eq(3);

 

  • tag로 Object 찾기

$() 안에 해당 tag를 입력하여 사용할 수 있습니다. 또한 여러 개의 동일한 tag가 존재하는 경우 eq()를 이용하여 해당 인덱스에 해당하는 오브젝트를 선택할 수 있습니다. 

//javascript
document.getElementsByTagName('table');

//jQuery
$("table");

//첫번째 table
$("table").eq(0);

 

  • 속성으로 Object 찾기( [ ] )

해당 기능은 javascript는 제공하지 않으므로 별도의 함수를 만들어서 사용해야 합니다. 

[ ] 안에 속성명 또는 속성에 해당하는 값의 형태로 작성하여 사용할 수 있습니다. 

//jQuery
$('[type]'); // type 라는 속성을 가진 Object

$('[type="button"]'); // type이 button인 Object

$('[type="button"]').eq(1);

 

 

replace() 함수

  • 자바스크립트에서 특정문자 또는 특수문자를 제거할때 replace() 함수를 사용하는 경우 , #가 여러번 있는 문자열(주민번호,전화번호)을 단순히 replace('#','')로 하면, 처음 #기호만 삭제되고 나머지는 삭제되지 않습니다.
var testStr = "#1#2#3";
testStr.replace("#","");

//결과값 : 1#2#3



replace()함수와 정규식을 활용하여 Java의 replaceAll() 함수와 동일한 기능을 하도록 만들어 보겠습니다. 

var testStr = "#1#2#3";
testStr.replace(/\#/g,"");

//결과값 : 123

해당 코드를 이용하여 replaceAll() 함수를 생성하여 사용하도록 합니다.

 

 

추가내용

  • 자주쓰는 정규식
    • 특정문자 제거(#제거)   : str.replace(/\#/g,'');
    • 앞의 공백 제거           : str.replace(/^\s+/,'');
    • 뒤 공백 제거              : str.replace(/\s+$/,'');
    • 앞 공백 제거              : str.replace(/^\s+|\s+$/g,'');
    • 문자열 내의 공백 제거 : str.replace(/\s/g,'');
    • 줄바꿈 제거               : str.replace(/\n/g,'');
    • 엔터 제거                  : str.replace(/\r/g,'');
    • 0 제거                      : str.replace(/[^(1-9)]/gi,"");

XSS란?

XSS(cross-site scripting)는 웹페이지에 악의적인 스크립트 코드를 주입할 수 있는 취약점이다.

 

XSS(Cross Site Scripting) 방지를 위해 널리 쓰이는 훌륭한 lucy-xss-servlet-filter는 Servlet Filter 단에서 < 등의 특수 문자를 &lt; 등으로 변환해주며, 여러 가지 관련 설정을 편리하게 지정할 수 있어 정말 좋다.

그런데 그 처리가 form-data에 대해서만 적용되고 Request Raw Body로 넘어가는 JSON에 대해서는 처리해주지 않는다는 단점이 있다. 그래서 JSON을 주고 받는 API 서버의 경우에는 직접 처리를 해줘야 한다.

 

즉, Lucy는 RequestParameter관련한 지원만 해준다.

 

 

그래서 이를 보완하기 위해서 여러가지 방법이 있겠지만, 가장 많이 사용되는 방법인 Request를 Wrapping 하여 적용하도록 한다. (기존에 Lucy XSS Filter를 사용하고 있다는 가정하에 작성)

 

준비물 : 2개의 Java Class, web.xml, Lucy XSS Filter

 

# Lucy XSS Filter는 Maven Central Repository 에 배포되어 있다. pom.xml 에 아래와 같이 의존성을 선언한다.

1
2
3
4
5
<dependency>
    <groupId>com.navercorp.lucy</groupId>
    <artifactId>lucy-xss</artifactId>
    <version>X.X.X</version>
</dependency>
cs

 

 

RequestWrapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
 
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
import com.nhncorp.lucy.security.xss.XssFilter;
 
public class RequestWrapper extends HttpServletRequestWrapper {
    private byte[] b;
 
    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        XssFilter filter = XssFilter.getInstance("lucy-xss-sax.xml");
        b = new String(filter.doFilter(getBody(request))).getBytes("UTF-8");
    }
 
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bis = new ByteArrayInputStream(b);
        return new ServletInputStreamImpl(bis);
    }
 
    class ServletInputStreamImpl extends ServletInputStream {
        private InputStream is;
 
        public ServletInputStreamImpl(InputStream bis) {
            is = bis;
        }
 
        public int read() throws IOException {
            return is.read();
        }
 
        public int read(byte[] b) throws IOException {
            return is.read(b);
        }
    }
 
    public static String getBody(HttpServletRequest request) throws IOException {
        String body = null;
       BufferedReader br= null;
       StringBuilder sb= new StringBuilder();
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
               br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = br.read(charBuffer)) > 0) {
                   sb.append(charBuffer, 0, bytesRead);
                }
              
            } else {
               sb.append("");
            }
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (br!= null) {
                try {
                   br.close();
                } catch (IOException ex) {
                    throw ex;
                }
            }
        }
        body = sb.toString();
        return body;
    }
}
 
cs

 

실제 필터링 기능을 수행하는 Java class이다. 

주의할 부분은 해당 작업을 수행할 경우 한글이 깨져서 chain.doFilter(requestWrapper, response);가 수행될 때 Json 오류가 날 수 있다.

그러므로 br= new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 항목에 인코딩 설정을 명시해서 해당 오류를 피해 가도록 한다.

 

 

 

RequestBodyXSSFIleter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class RequestBodyXSSFIleter implements Filter {
    private List<String> extUrl;
 
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
       RequestWrapper reqWrapper = null;
        String path = ((HttpServletRequest) req).getServletPath();
 
        try {
            if (!extUrl.contains(path)) {
              
               reqWrapper = new RequestWrapper(request);
               chain.doFilter(reqWrapper , response);
            } else {
                chain.doFilter(request, response);
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
 
    }
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String excludePattern = filterConfig.getInitParameter("extUrls");
       extUrl = Arrays.asList(excludePattern.split(","));
    }
 
    @Override
    public void destroy() {
    }
}
 
cs

 

requestBody에 XSS Filter를 적용할 경우 Multipart(일반적으로 파일 업로드) 일 때 파일이 손상되는 일이 발생한다.

이를 방지하기위해 파일을 송신하는 URL의 경우 web.xml의 init-param을 이용하여 필터링을 제외할 수 있다.

 

RequestBodyXSSFIleter의 init시 filterConfig에서 해당 파라미터에 접근하여 제외할 URL목록을 콤마(,)로 구분하여 작성 후 필터를 적용하지 않는 방법으로 우회할 수 있다.

 

 

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    <!-- Xss Filter Start -->
    <filter>
        <filter-name>xssEscapeServletFilter</filter-name>
        <filter-class>com.navercorp.lucy.security.xss.servletfilter.XssEscapeServletFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>xssEscapeServletFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <filter>
        <filter-name>RequestBodyXSSFilter</filter-name>
        <filter-class>com.your.pkg.path.filter.RequestBodyXSSFIleter</filter-class>
        <init-param>
            <param-name>extUrls</param-name>
            <param-value>/linkUrl1,/linkUrl2,/linkUrl2</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>RequestBodyXSSFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- Xss Filter End -->
cs

 

서버 정보 노출 및 에러코드의 노출을 방지하기 위해 대부분의 사이트가 HTTP 403, 404 등 HTTP 에러 발생 시 별도의 에러 페이지로 리다이렉트 시키고 있다.

 

하지만 헤더정보를 통해 에러정보를 노출 시키고 있다. 

 

따라서 Error Page에서 Http Status를 강제로 고정시키는 처리가 필요하다. 

 

리다이렉트 되는 에러페이지에 <%response.setStatus(200);%> 입력 시 에러 페이지로 리다이렉트와 동시에 헤더 정보내 노출되는 에러코드 노출을 방지할 수 있다.



1
2
3
4
5
6
7
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<% response.setStatus(200); %>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
cs

 

투명한 DIV가 필요한경우            background-colorrgba(255,255,255,0.4);


RGBA다.. RGB가 아니고.. 알파값을 주는 방법이다.


투명하게 설정하는 방법이 여러가지가 있는데 이경우는 해당 레이어만 반투명이 적용 되는 케이스이다. 


레이어가 자식으로 가지고 있는 객체는 투명해지지 않는다.

'Web > CSS' 카테고리의 다른 글

DIV 가로/세로 중앙에 위치하기  (0) 2018.02.21

가변적인 브라우저의 크기의 경우 특정 DIV를 정중앙에 위치시킬 때 관련 블로그에 내용이 상당히 많이 나와 있긴하다.

예를 들면 iniline-block로 해서 문자로 인식하게 해서 text-align Center를 준다던가...(이러면 안에 모든 텍스트가 중앙정렬된다 ㅠㅠ)


이것 저것 고민하다가 아래와 같은 css 코드로 해결하였다.



  1. positionabsolute;
  2. top50%;
  3. left50%;
  4. transformtranslate(-50%,-50%);
  5. -ms-transformtranslate(-50%,-50%);


'Web > CSS' 카테고리의 다른 글

반투명한 Div 만들기  (0) 2018.02.21

+ Recent posts