프로그래밍/- eGov

filter 에서 xss 보안처리

즐겁게 하하하 2025. 1. 17. 21:19
728x90

web.xml

<!-- 필터 등록 -->
<filter>
    <filter-name>baseFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>baseFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>

<filter>
    <filter-name>baseXssFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>baseXssFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

DelegatingFilterProxy란?

  • Spring Framework에서 제공하는 필터 구현체로, 실제 필터링 로직을 Spring Context에 정의된 Bean으로 위임(delegate)합니다.
  • Java Servlet 필터를 구현하고, Spring IoC 컨테이너 안에서 관리되는 Bean과 연동하기 위해 사용됩니다.

 

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.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Service("baseXssFilter")
public class XSSFilter implements Filter {

   protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 필터 초기화 작업 (필요시 사용)
    }

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

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        try { 
            // 요청 파라미터에서 악성 스크립트 감지 
            if (containsMaliciousScript(httpRequest)) { 
                // 악성 스크립트 발견 시 에러 페이지로 이동 
                handleMaliciousScript(httpRequest, httpResponse); 
                return; 
            } 
        } catch (Exception e) { 
            // 예외 처리 
            handleException(httpRequest, httpResponse, e); 
        } 

        HttpServletRequest httpRequest = (HttpServletRequest) request; 
        XSSUrlRequestWrapper wrappedRequest = new XSSUrlRequestWrapper(httpRequest); 
        chain.doFilter(wrappedRequest , response); 
    }
  
     /** 
     * URL 파라미터에서 악성 스크립트가 포함되어 있는지 검사 
     */ 
    private boolean containsMaliciousScript(HttpServletRequest request) {

        // 모든 파라미터 검사 
        for (String param : request.getParameterMap().keySet()) { 
            String[] values = request.getParameterValues(param); 
            if (values != null) { 
                for (String value : values) { 
                    if (isMalicious(value)) { 
                        return true; // 악성 값 발견 
                    } 
                } 
            } 
        } 
        return false; // 악성 값 없음 
    }
 
     /** 
     * 문자열에서 악성 스크립트를 탐지 
     */ 
    private boolean isMalicious(String value) {

        if (value == null) return false;
 
        // 간단한 패턴 탐지: 스크립트 태그, JavaScript 이벤트, 기타 악성 코드 
        String lowerValue = value.toLowerCase(); 
        return lowerValue.contains("<script") || lowerValue.contains("javascript:") 
                || lowerValue.matches(".*on[a-z]+\\s*=.*") 
                || lowerValue.contains("<img") && lowerValue.contains("onerror"); 
    }
 
    private void handleMaliciousScript(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException { 
			
        // 에러 메시지 설정 
        response.setStatus(HttpServletResponse.SC_NOT_FOUND); // 상태 코드 설정 
        request.setAttribute("javax.servlet.error.status_code", HttpServletResponse.SC_NOT_FOUND); // 추가 설정 
        request.setAttribute("errorMsg", "악성 스크립트가 감지되었습니다. 요청이 차단되었습니다.");
 
        // 내부 JSP로 포워딩  
        RequestDispatcher dispatcher = request.getRequestDispatcher("/error.do"); 
        dispatcher.forward(request, response); 
    }
 
    private void handleException(HttpServletRequest request, HttpServletResponse response, Exception e) 
            throws ServletException, IOException {
 
        // 예외 메시지 설정 
        request.setAttribute("errorMsg", "예기치 못한 에러가 발생했습니다: " + e.getMessage());
 
        // 내부 JSP로 포워딩 
        RequestDispatcher dispatcher = request.getRequestDispatcher("/error.do"); 
        dispatcher.forward(request, response); 
    }
 
    @Override 
    public void destroy() { 
        // 필터 종료 작업 (필요시 사용) 
    } 
}
728x90