study/Project 🐾

[Java] RequestRejectedException 처리

서나쓰 2022. 8. 23. 17:42
728x90
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String "//"
	at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlocklistedUrls(StrictHttpFirewall.java:456)
	at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:429)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:196)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)

 

운영 시스템 로그 확인하던 중에 만난 에러 로그 

처음 보는 에러 로그이기도 하고 검색해보니 Spring security와 관련된 예외라고 한다

확인해보니 이미 예전부터 발생한 에러인데 로그를 잘 확인 안 하다보니 처음 발견..

해석해보면 "//" 의 요청이 접근 제한되었다는 내용이다

”//” 이외에도 org.springframework.security.web.firewall.StrictHttpFirewall 클래스를 확인해보면 아래처럼 여러 [블랙리스트 문자열] 이 있는 것을 확인 할 수 있다.

private static final List<String> FORBIDDEN_ENCODED_PERIOD = Collections.unmodifiableList(Arrays.asList("%2e", "%2E"));
private static final List<String> FORBIDDEN_SEMICOLON = Collections.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));
private static final List<String> FORBIDDEN_FORWARDSLASH = Collections.unmodifiableList(Arrays.asList("%2f", "%2F"));
private static final List<String> FORBIDDEN_DOUBLE_FORWARDSLASH = Collections.unmodifiableList(Arrays.asList("//", "%2f%2f", "%2f%2F", "%2F%2f", "%2F%2F"));
private static final List<String> FORBIDDEN_BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));
private Set<String> encodedUrlBlacklist = new HashSet<>();
private Set<String> decodedUrlBlacklist = new HashSet<>();
private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods();
private Predicate<String> allowedHostnames = hostname -> true;

public StrictHttpFirewall() {
	urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
	urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
	urlBlacklistsAddAll(FORBIDDEN_DOUBLE_FORWARDSLASH);
	urlBlacklistsAddAll(FORBIDDEN_BACKSLASH);

	this.encodedUrlBlacklist.add(ENCODED_PERCENT);
	this.encodedUrlBlacklist.addAll(FORBIDDEN_ENCODED_PERIOD);
	this.decodedUrlBlacklist.add(PERCENT);
}

구글링에 "//"을 허용하는 해결책이 있긴 한데 굳이 막아놓은 걸 허용할 필요가 있나 싶어서 필터링에 걸리면 로그에 찍히지 않게만 처리하고자 한다.

@Aspect
@Component
public class FilterChainProxyAdvice {

    @Around("execution(public void org.springframework.security.web.FilterChainProxy.doFilter(..))")
    public void handleRequestRejectedException (ProceedingJoinPoint pjp) throws Throwable {
        try {
            pjp.proceed();
        } catch (RequestRejectedException exception) {
            HttpServletResponse response = (HttpServletResponse) pjp.getArgs()[1];
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        }
    }
}

AOP 를 이용한 방법인데 대충 설명하자면 Around의 타겟 메소드로 doFIlter를 잡아서 익셉션 처리를 하는것이다.

pjp.proceed();

에서 doFilter가 실행되면서 “//” 문자열이 URL에 포함되어 들어오면 RequestRejectedException 을 발생시키는데, 해당 Exception을 잡아서 로그가 안찍히게 해주면된다.

728x90