요약
1. 필터추가 (프로젝트별 방법 상이)
- WebInitializer.java (수정)
2. 소스추가
- XSSFilter.java
- XSSFilterWrapper.java
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
상세
1. WebInitializer.java (수정)
- new XSSFilter() 추가
protected Filter[] getServletFilters() {
OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
openEntityManagerInViewFilter.setEntityManagerFactoryBeanName("entityManagerFactory");
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] {
openEntityManagerInViewFilter,
characterEncodingFilter,
new DelegatingFilterProxy("springSecurityFilterChain"),
new MDCInsertingServletFilter(),
new XSSFilter(),
new HiddenHttpMethodFilter(),
};
}
2. XSSFilter.java (추가)
- 필터 예외 URL 알맞게 수정
package com.plugin.xss;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
public class XSSFilter implements Filter {
public FilterConfig filterConfig;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
//필터 예외 URL 알맞게 수정
if (!path.contains("/api/common")) {
chain.doFilter(new XSSFilterWrapper((HttpServletRequest) request), response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
@Override
public void destroy() {
this.filterConfig = null;
}
}
3. XSSFilterWrapper.java (추가)
package com.plugin.xss;
import com.util.LogUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.Map;
@Slf4j
public class XSSFilterWrapper extends HttpServletRequestWrapper {
private byte[] rawData;
public XSSFilterWrapper(HttpServletRequest request) {
super(request);
try {
InputStream inputStream = request.getInputStream();
this.rawData = replaceXSS(IOUtils.toByteArray(inputStream));
} catch (Exception e) {
log.info(LogUtil.getFullLogMessage(e));
}
}
// XSS replace
private byte[] replaceXSS(byte[] data) {
String strData = new String(data);
strData = stripXSS(strData);
return strData.getBytes();
}
private String replaceXSS(String value) {
if (value != null) {
value = stripXSS(value);
}
return value;
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (this.rawData == null) {
return super.getInputStream();
}
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.rawData);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
@Override
public String getQueryString() {
return replaceXSS(super.getQueryString());
}
@Override
public String getParameter(String name) {
return replaceXSS(super.getParameter(name));
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> params = super.getParameterMap();
if (params != null) {
params.forEach((key, value) -> {
for (int i = 0; i < value.length; i++) {
value[i] = replaceXSS(value[i]);
}
});
}
return params;
}
@Override
public String[] getParameterValues(String name) {
String[] params = super.getParameterValues(name);
if (params != null) {
for (int i = 0; i < params.length; i++) {
params[i] = replaceXSS(params[i]);
}
}
return params;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(), "UTF-8"));
}
private String stripXSS(String value) {
if (value != null) {
//공통
value = value.replaceAll("(?i)<script>(.*?)</script>", "");
value = value.replaceAll("(?i)src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", "");
value = value.replaceAll("(?i)src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", "");
value = value.replaceAll("(?i)</script>", "");
value = value.replaceAll("(?i)<script(.*?)>", "");
value = value.replaceAll("(?i)eval\\((.*?)\\)", "");
value = value.replaceAll("(?i)expression\\((.*?)\\)", "");
//공공 가이드
value = value.replaceAll("(?i)javascript", "");
value = value.replaceAll("(?i)expressicharset", "");
value = value.replaceAll("(?i)applet", "");
//value = value.replaceAll("(?i)document", "");
//value = value.replaceAll("(?i)meta", "");
//value = value.replaceAll("(?i)string", "");
//value = value.replaceAll("(?i)xml", "");
value = value.replaceAll("(?i)create", "");
value = value.replaceAll("(?i)blink", "");
value = value.replaceAll("(?i)append", "");
value = value.replaceAll("(?i)link", "");
value = value.replaceAll("(?i)binding", "");
//value = value.replaceAll("(?i)style", "");
value = value.replaceAll("(?i)alert", "");
value = value.replaceAll("(?i)script", "");
value = value.replaceAll("(?i)msgbox", "");
value = value.replaceAll("(?i)cnbeforeprint", "");
value = value.replaceAll("(?i)embed", "");
value = value.replaceAll("(?i)refresh", "");
value = value.replaceAll("(?i)cnbeforepaste", "");
//value = value.replaceAll("(?i)object", "");
//value = value.replaceAll("(?i)void", "");
value = value.replaceAll("(?i)iframe", "");
value = value.replaceAll("(?i)cookie", "");
value = value.replaceAll("(?i)frame", "");
value = value.replaceAll("(?i)href", "");
value = value.replaceAll("(?i)frameset", "");
value = value.replaceAll("(?i)ilayer", "");
value = value.replaceAll("(?i)layer", "");
value = value.replaceAll("(?i)bgsound", "");
//value = value.replaceAll("(?i)base", "");
//value = value.replaceAll("(?i)title", "");
value = value.replaceAll("(?i)vbscript", "");
//공공 가이드 (event)
value = value.replaceAll("(?i)onmousewheel(.*?)=", "");
value = value.replaceAll("(?i)onactive(.*?)=", "");
value = value.replaceAll("(?i)onfocusout(.*?)=", "");
value = value.replaceAll("(?i)on(.*?)=", "");
value = value.replaceAll("(?i)ondataavailable(.*?)=", "");
value = value.replaceAll("(?i)oncut(.*?)=", "");
value = value.replaceAll("(?i)onkeyup(.*?)=", "");
value = value.replaceAll("(?i)onafteripudate(.*?)=", "");
value = value.replaceAll("(?i)onclick(.*?)=", "");
value = value.replaceAll("(?i)onkeypress(.*?)=", "");
value = value.replaceAll("(?i)onmousedown(.*?)=", "");
value = value.replaceAll("(?i)onchange(.*?)=", "");
value = value.replaceAll("(?i)onload(.*?)=", "");
value = value.replaceAll("(?i)onbeforeactivate(.*?)=", "");
value = value.replaceAll("(?i)onbeforecut(.*?)=", "");
value = value.replaceAll("(?i)onbounce(.*?)=", "");
value = value.replaceAll("(?i)onbeforecopy(.*?)=", "");
value = value.replaceAll("(?i)ondbclick(.*?)=", "");
value = value.replaceAll("(?i)onmouseenter(.*?)=", "");
value = value.replaceAll("(?i)onbeforedeactivate(.*?)=", "");
value = value.replaceAll("(?i)ondeactivate(.*?)=", "");
value = value.replaceAll("(?i)onmouseout(.*?)=", "");
value = value.replaceAll("(?i)ondatasetchaged(.*?)=", "");
value = value.replaceAll("(?i)ondrag(.*?)=", "");
value = value.replaceAll("(?i)onmouseover(.*?)=", "");
value = value.replaceAll("(?i)ondragend(.*?)=", "");
value = value.replaceAll("(?i)onsubmit(.*?)=", "");
value = value.replaceAll("(?i)ondragenter(.*?)=", "");
value = value.replaceAll("(?i)onmouseend(.*?)=", "");
value = value.replaceAll("(?i)onbeforeeditfocus(.*?)=", "");
value = value.replaceAll("(?i)ondragleave(.*?)=", "");
value = value.replaceAll("(?i)onresizestart(.*?)=", "");
value = value.replaceAll("(?i)onbeforeuload(.*?)=", "");
value = value.replaceAll("(?i)ondragover(.*?)=", "");
value = value.replaceAll("(?i)onuload(.*?)=", "");
value = value.replaceAll("(?i)onbeforeupdate(.*?)=", "");
value = value.replaceAll("(?i)ondragstart(.*?)=", "");
value = value.replaceAll("(?i)onselectstart(.*?)=", "");
value = value.replaceAll("(?i)onpaste(.*?)=", "");
value = value.replaceAll("(?i)onpropertychange(.*?)=", "");
value = value.replaceAll("(?i)ondrop(.*?)=", "");
value = value.replaceAll("(?i)onreset(.*?)=", "");
value = value.replaceAll("(?i)onresize(.*?)=", "");
value = value.replaceAll("(?i)ondatasetcomplete(.*?)=", "");
value = value.replaceAll("(?i)onerror(.*?)=", "");
value = value.replaceAll("(?i)onmove(.*?)=", "");
value = value.replaceAll("(?i)onselect(.*?)=", "");
value = value.replaceAll("(?i)oncellchange(.*?)=", "");
value = value.replaceAll("(?i)onfinish(.*?)=", "");
value = value.replaceAll("(?i)onstop(.*?)=", "");
value = value.replaceAll("(?i)onlayoutcomplete(.*?)=", "");
value = value.replaceAll("(?i)onfocus(.*?)=", "");
value = value.replaceAll("(?i)onrowexit(.*?)=", "");
value = value.replaceAll("(?i)onblur(.*?)=", "");
value = value.replaceAll("(?i)onselectionchange(.*?)=", "");
value = value.replaceAll("(?i)onerrorupdate(.*?)=", "");
value = value.replaceAll("(?i)onbefore(.*?)=", "");
value = value.replaceAll("(?i)onstart(.*?)=", "");
value = value.replaceAll("(?i)onrowsinserted(.*?)=", "");
value = value.replaceAll("(?i)onkeydown(.*?)=", "");
value = value.replaceAll("(?i)onfilterchage(.*?)=", "");
value = value.replaceAll("(?i)onmouseup(.*?)=", "");
value = value.replaceAll("(?i)onfocusin(.*?)=", "");
value = value.replaceAll("(?i)oncontrolselected(.*?)=", "");
value = value.replaceAll("(?i)onrowsdelete(.*?)=", "");
value = value.replaceAll("(?i)onlosecapture(.*?)=", "");
value = value.replaceAll("(?i)onrowenter(.*?)=", "");
value = value.replaceAll("(?i)onhelp(.*?)=", "");
value = value.replaceAll("(?i)onreadystatechange(.*?)=", "");
value = value.replaceAll("(?i)onmouseleave(.*?)=", "");
value = value.replaceAll("(?i)onmousemove(.*?)=", "");
value = value.replaceAll("(?i)oncontextmenu(.*?)=", "");
}
return value;
}
}
반응형