본문 바로가기

해킹-보안

Spring XSS Java Filter 등록하기

반응형

일반적인 웹 환경에서는 클라이언트 요청이 DispatcherServlet로 전송되지만
Java Filter 등록 후 ServletFilter를 먼저 통과하게 된다.
따라서 Java Filter를 이용해 서버에 들어오는 모든 요청 값을 ServletFilter에서 필터링 할 수 있다.

먼저 필터를 등록하기 위한 2개의 Java Class와 web.xml 파일을 설정해야 한다.

CrossScriptingFilter 필터 파일
 package com.sec.secprj.controller;
 
 import java.io.BufferedReader;
 import java.io.IOException;
  
 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;
 
 public class CrossScriptingFilter 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 {
         
         // Filter 처리
         chain.doFilter(new RequestWrapper((HttpServletRequest) request), response);
        
     }
 }
1. doFilter request를 통해 클라이언트 요청 필터링
2. RequestWrapper 클래스를 통해 클라이언트의 변경 요청
3. chain.DoFilter를 통해 응답을 필터링
4. doFilter 메서드의 세 번째 파라미터인 chain 메서드를 통해 반복적인 doFilter 호출


RequestWrapper 필터링
 package com.sec.secprj.controller;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
  
 public 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) {
     	// 필터링을 수행한다.
   		value = value.replaceAll("&", "&amp;")
   				 .replaceAll("<", "&lt;")
   				 .replaceAll(">","&gt;")
   				 .replaceAll("\"", """) 
   				 .replaceAll("\'", "'")
   				 .replaceAll("%", "&#37;")
   				 .replaceAll("%2F", "");
   		System.out.print("aa" + value);
           return value;
       }
  
 }
Wrapper 클래스는 클라이언트 요청을 변경하여 서블릿으로 전달하고 응답 결과를 반영하여
클라이언트에게 보내는 역할을 한다.

web.xml
 <filter>
     <filter-name>CrossScriptingFilter</filter-name>
     <filter-class>com.sec.secprj.controller.CrossScriptingFilter</filter-class>
   </filter>
   <filter-mapping>
     <filter-name>CrossScriptingFilter</filter-name>
     <url-pattern>/*</url-pattern>
   </filter-mapping>
ServletFilter를 관리하기 위해 Spring에 설정된 서블릿 필터 빈 객체를 통과하도록 web.xml을 설정한다.

HTTP Request로 넘어온 파라미터 중 일부 값들은 getParameter()나 getParameterValues()로 읽을 수 없는 경우가 있다. 
POST 방식으로 전송된 json 형태의 body 데이터는 Request.getInputStream() 혹은 Request.getReader()를 통해 
직접 조회하거나 @RequestBody 어노테이션을 통해 HTTP 요청 body 데이터를 자바 객체로 변환하여 전달한다.

 

반응형