input태그에 스크립트 방지하는 방법(XSS 방지)
프로젝트 테스트기간이라 몇가지 수정해달라는 요청받았다.
엑셀로 받았는데 수정사항 내용이 글제목에 태그가 입력됨.
으로 왔길래 무슨 말일까 고민하고있었다.
팀장님이 “XSS방어하면 돼요~”라고 말씀해준 뒤에야 이해할 수 있었다.
아 html태그를 말하는 거였구나.
태그가 입력된다는 말이 진짜 html태그가 들어간다는 말이었구나.
XSS란?
XSS란 Cross-site scriptiong에 약어로 input태그에 자바스크립트 함수등의 실행코드를 고의로 작동시켜 해당 사이트를 마음대로 컨트롤하며 Data등을 빼내갈 수 있는 공격법이다.
예를 들어 게시글을 수정할때 input태그에 <script>alert('XSS테스트');</script>
를 입력한 뒤 글 수정버튼을 클릭하면 서버사이드랜더링으로 출력되는 값을 그대로 실행하기 때문에 XSS되어 alert창이 실행된다.
간단한 alert창이어서 망정이지 DB를 접근하거나 아예 사이트를 제어하는 스크립트를 실행시키는 경우 보안상 큰 문제가 발생할 수 있다.
1 Service에서 XSS 방어하기
XSS를 방어하기 위해서 서버측에서 필터링을 걸어야한다.
구글링을 통해 다양한 방법을 찾을 수 있다.
보통 script, iframe, embed는 보안에 취약할 수 있기에 꼭 삭제해줘야한다.
- XssUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class XssUtil {
public static String cleanXSS(String value) {
String returnVal = value;
returnVal = returnVal.replaceAll("<", "<").replaceAll(">", ">");
returnVal = returnVal.replaceAll("\\(", "(").replaceAll("\\)", ")");
returnVal = returnVal.replaceAll("'", "'");
returnVal = returnVal.replaceAll("eval\\((.*)\\)", "");
returnVal = returnVal.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
returnVal = returnVal.replaceAll("script", "");
returnVal = returnVal.replaceAll("iframe", "");
returnVal = returnVal.replaceAll("embed", "");
return returnVal;
}
}
그리고 호출은 서비스에서 진행하면된다.
- BoardServiceImpl.java
1
2
3
4
5
6
7
public void updateBoard(BoardInfo info) {
info.setSubject(XssUtil.cleanXSS(info.getSubject()));
// 중략
boardDao.updateBoard(info);
}
2 JAVA fILTER를 통해 XSS 방어
XSSFilter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class XSSFilter implements Filter {
public FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new RequestWrapper((HttpServletRequest) request), response);
}
}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
49public final class RequestWrapper extends HttpServletRequestWrapper {
public RequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
}
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values==null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = cleanXSS(values[i]);
}
return encodedValues;
}
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return cleanXSS(value);
}
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null)
return null;
return cleanXSS(value);
}
private String cleanXSS(String value) {
String returnVal = value;
returnVal = returnVal.replaceAll("<", "<").replaceAll(">", ">");
returnVal = returnVal.replaceAll("\\(", "(").replaceAll("\\)", ")");
returnVal = returnVal.replaceAll("'", "'");
returnVal = returnVal.replaceAll("eval\\((.*)\\)", "");
returnVal = returnVal.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
returnVal = returnVal.replaceAll("script", "");
returnVal = returnVal.replaceAll("iframe", "");
returnVal = returnVal.replaceAll("embed", "");
return returnVal;
}
}
- web.xml 에 필터설정 추가
1
2
3
4
5
6
7
8<filter>
<filter-name>XSS</filter-name>
<filter-class>com.test.api.XSSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XSS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3 lucy 라이브러리 사용
네이버에서 만든 lucy-xss-filter(링크) 라이브러리가 있다.
링크에 접속하면 한국어로 친절히 설명되어있다.
pom.xml파일과 web.xml파일, lucy-xss-servlet-filter-rule.xml파일을 설정해주면 된다!
가장 사용하기 좋은 방법이 아닐까한다. 실제로 1번 방식으로 했다가 3번방식으로 바꿨다!