* 기본개념
XSS(Cross Site Scripting)는 공격자에 의해 작성된 스크립트가 다른 사용자에게 전달되는 것이다. 다른 사용자의 웹 브라우저 내에서 적절한 검증 없이 실행되기 때문에 사용자의 세션을 탈취하거나, 웹 사이트를 변조하거나 혹은 악의적인 사이트로 사용자를 이동시킬 수 있다. XSS은 일반적으로 [그림 4-39]와 같은 구조를 통해 이루어진다.
[네이버 지식백과] XSS 취약점 (정보 보안 개론, 2013. 6. 28., 양대일)
* 3가지 형태의크로스 사이트 스크립팅(xss)
1). Reflected XSS ( 반사 XSS )
반사식 XSS 공격은 검색 결과, 에러 메시지 등 서버가 외부에서 입력 받은 값을 받아 브라우저에게 응답할 때 전송하는 과정에서 입력되는 변수의 위험한 문자를 사용자에게 그대로 돌려주면서 발생한다.
ex) index.php?page=error&value=<script>alert(document.cookie)</script>
2). Stored XSS
악성 스크립트를 영구히 저장해 놓는 방법. 게시판 등에 악성 스크립트를 삽입해 놓으면, 사용자가 사이트를 방문하여 악성 스크립트가 저장되어있는 페이지에 정보를 요청할 때, 서버는 악성 스크립트를 사용자에게 전달하여 사용자 브라우저에서 스크립트가 실행되면서 공격한다.
3). DOM XSS
DOM(Document Object Model) 데이터 접근 시 검증되지 않은 값이 자바 스크립트를 통해 삽입되어 발생하는 취약점이다.
* 처리방법
1. Apache Commons의 StringEscapeUtils.escapeHtml4() 사용
2. JSTL의 <c:out> 또는 EL의 fn:escapeXML() 사용
* 사용방법
1. Apache Commons의 StringEscapeUtils.escapeHtml4() 사용
[pom.xml] <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency>
commons-lang3의 StringEscapeUtils은 더 이상 지원되지 않는다. commons-lang3이 높은 버전일 경우 아래의 dependency를 사용한다.
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>3.4</version> </dependency>
[JAVA] public String getStr(String param) { return StringEscapeUtils.escapeHtml4(param); }
|
2. JSTL의 <c:out> 또는 EL의 fn:escapeXML() 사용
<p><c:out value="${user.userId}"></p> <p><input name="foo" value="${fn:escapeXml(user.userId)}"></p> |
3. Lucy XSS Filter 사용 (네이버 무료 배포하는 자바기반의 필터 라이브러리이다.)
Lucy XSS Filter는 사용 방식에 따라 Lucy XSS Filter, Lucy XSS Servlet Filter 두 가지가 있다.
Lucy XSS Servlet Filter는 servlet에 장착하는 필터이다. 이것의 장점은 servlet단에 장착을 함으로써 모든 파라미터에 적용이 가능하다는 것이다. Lucy XSS Filter라면 필요한 곳에 일일이 처리를 해줘야 하지만 servlet 필터에 넣어 놓으면 모든 파라미터에 적용이 되므로 별도의 코드 수정이 필요가 없다. 하지만 JSON 처리는 따로 해줘야하는 단점이 있다. |
3-1 JSON에 대한 XSS처리 (퍼온글)
Jackson 같은 Mapper를 통해 JSON 문자열로 Response에 담겨지므로, Mapper가 JSON 문자열을 생성할 때 XSS 방지 처리를 해주면 될 것 같다.
|
처리할 특수 문자 지정
XSS 방지 처리할 특수 문자를 다음과 같이 CharacterEscapes를 상속한 클래스를 직접 만들어서 지정해준다.
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
|
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;
import org.apache.commons.lang3.text.translate.AggregateTranslator;
import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
import org.apache.commons.lang3.text.translate.EntityArrays;
import org.apache.commons.lang3.text.translate.LookupTranslator;
public class HTMLCharacterEscapes extends CharacterEscapes {
private final int[] asciiEscapes;
private final CharSequenceTranslator translator;
public HTMLCharacterEscapes() {
// 1. XSS 방지 처리할 특수 문자 지정
asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
asciiEscapes['<'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['>'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['&'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['\"'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['('] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes[')'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['#'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['\''] = CharacterEscapes.ESCAPE_CUSTOM;
// 2. XSS 방지 처리 특수 문자 인코딩 값 지정
translator = new AggregateTranslator(
new LookupTranslator(EntityArrays.BASIC_ESCAPE()), // <, >, &, " 는 여기에 포함됨
new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE()),
new LookupTranslator(EntityArrays.HTML40_EXTENDED_ESCAPE()),
// 여기에서 커스터마이징 가능
new LookupTranslator(
new String[][]{
{"(", "("},
{")", ")"},
{"#", "#"},
{"\'", "'"}
}
)
);
}
@Override
public int[] getEscapeCodesForAscii() {
return asciiEscapes;
}
@Override
public SerializableString getEscapeSequence(int ch) {
return new SerializedString(translator.translate(Character.toString((char) ch)));
// 참고 - 커스터마이징이 필요없다면 아래와 같이 Apache Commons Lang3에서 제공하는 메서드를 써도 된다.
// return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
}
}
|
cs |
ObjectMapper에 특수 문자 처리 기능 적용 후 MessageConverter 등록
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
|
@Bean
public WebMvcConfigurerAdapter controlTowerWebConfigurerAdapter() {
return new WebMvcConfigurerAdapter() {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
// 5. WebMvcConfigurerAdapter에 MessageConverter 추가
converters.add(htmlEscapingConveter());
}
private HttpMessageConverter<?> htmlEscapingConveter() {
ObjectMapper objectMapper = new ObjectMapper();
// 3. ObjectMapper에 특수 문자 처리 기능 적용
objectMapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());
// 4. MessageConverter에 ObjectMapper 설정
MappingJackson2HttpMessageConverter htmlEscapingConverter =
new MappingJackson2HttpMessageConverter();
htmlEscapingConverter.setObjectMapper(objectMapper);
return htmlEscapingConverter;
}
};
}
|
cs |
https://github.com/naver/lucy-xss-servlet-filter
https://github.com/naver/lucy-xss-filter
참고사이트
'dev > 자바' 카테고리의 다른 글
[자바] Eclipse 에서 DCEVM 사용하기(서버재구동안하기.) (0) | 2021.02.19 |
---|---|
JRABEL 라이센스발급, 설치 (0) | 2021.01.11 |
JAVA try-with-resources문 (0) | 2020.05.31 |
JAVA 익명클래스 (0) | 2020.05.31 |
[JNDI] eclipse에서 jndi 설정테스트 (0) | 2014.11.20 |