Geneuin
Geneuin
1 min read

Categories

페이지 목차

  1. filter와 interceptor의 차이
  2. filte를 통한 크로스사이트스크립트 처리

filter를 통한 크로스사이트스크립트 처리

  • 전 포스팅에서 언급한 filter를 통한 크로스사이트스크립트 예외처리에 관하여 서술하겠다. 크로스사이트스크립트란? 크로스 사이트 스크립팅은 웹사이트에 악성 스크립트를 주입하는 행위를 말한다. 해커는 사람들이 친밀하고 안전하다고 생각하는 웹사이트에 악성 스크립트를 주입하고, 악성 스크립트가 포함된 게시글을 열람한 피해자들의 쿠키는 해커에게 전송한다. 이를 통해 해커는 피해자의 브라우저에서 스트립트를 실행해 사용자의 세션을 가로채거나, 웹사이트 변조하거나, 악의적인 컨텐츠 삽입하거나, 피싱 공격 등을 시도할 수 있게 된다. #참조: https://nordvpn.com/ko/blog/xss-attack/

예를들면

<input type="text" placeholder="검색어를 입력하세요." id="searchKeyword" name="searchKeyword" value="${searchVO.searchKeyword}" />

위와 같은 문구가 있을때,

/test.do?searchKeyword="/><script>alert(1)</script> 

와같은 호출을 진행하면, 아래와 같이 script 가 실행됨을 확인 할 수 있다. 1-2

##필자는 이를 filter를 통하여 처리하는 방법으로 구현 하였다. 아래는 그 구현 소스다.

@Component
public class CrossScriptingFilter implements Filter {

	FilterConfig filterConfig;

	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
	}

	public void destroy() {
		this.filterConfig = null;
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
		throws IOException, ServletException {

		chain.doFilter(new RequestWrapper((HttpServletRequest) request), response);

	}

}


public 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] = CleanXssUtil.cleanXSS(values[i]);
		}
		return encodedValues;
	}

	public String getParameter(String parameter) {
		String value = super.getParameter(parameter);
		if (value == null) {
			return null;
		}
		return CleanXssUtil.cleanXSS(value);
	}

	public String getHeader(String name) {
		String value = super.getHeader(name);
		if (value == null)
			return null;
		return CleanXssUtil.cleanXSS(value);

	}


}


public class CleanXssUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(CleanXssUtil.class);
	/**
	 * 사용자에 대한 크로스사이트스크립트(Xss) 확인한다.
	 * 수정, 상세조회, 삭제시 사용
	 * @return boolean
	 * @exception IllegalArgumentException
	 */
	public static String cleanXSS(String value) {
		//You'll need to remove the spaces from the html entities below
		value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
		value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
		value = value.replaceAll("'", "& #39;");
		value = value.replaceAll("eval\\((.*)\\)", "");
		value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
		value = value.replaceAll("script", "");
		return value;
	}

}


우선 filter를 implements를 받는다. 그럼 전편에서 설명한것과 같이, 필터가 등록되고 모든 요청은 디스패처서블릿에 도달하기전 doFilter를 통과한다. FilterChain의 doFilter를통해 디스패처 서블릿으로 넘기기전, 모든 요청에 대한 request body를 확인할 필요가 었다. request를 통해 모든 요청을 확인 할 수 있지만, 필자는 그부분은 HttpServletRequestWrapper 를 사용하였다. HttpServletRequestWrapper를 통해 각 request body의 내용을 확인하고, CleanXssUtil를통해 문제가 될 수 있는 문자들을 모두 치환해 주었다.

  • references:
  • Written by: 이재봉 (jblee6110@gmail.com)
  • reporting date: 2023-07-07