[Spring Security] RequestRejectedException과 HttpFirewall

Y_Sevin·2023년 12월 10일
0


헤어비 서비스를 운영하며 종종 위와 같은 exception이 발생하였다. 서비스에서 허용하지 않은 HTTP method와 URL에 잠재적으로 악의적인 문자열 "%2e"가 포함되어 이를 거부한다는 메세지인데, 이는 스프링 시큐리티에서 제공하는 기능 중 하나이다.

서비스에 악의적인 요청으로 인해 해당 exception을 발생시키는 것임은 알았지만, 왜 해당 문자열을 거부하는 것이고 어떻게 스프링 시큐리티의 어떤 기능으로 이를 방지한 것인지 좀더 자세히 알아보고자 한다.

HttpFirewall이란?

Spring Security의 HttpFirewall은 웹 애플리케이션을 보호하기 위한 필터로, 잠재적으로 악의적인 요청을 차단한다. 필자의 경우 아래의 상황때문에 필터가 작동하였다.

1. 악의적인 문자열 포함
URL 인코딩된 문자열 %2e는 마침표(.)를 의미한다. 마침표는 파일 시스템 경로에서 상위 디렉토리를 참조할 때 사용될 수 있다. 예를 들어, ../와 같이 사용하면 상위 디렉토리로 이동할 수 있다. 만약 서버가 이러한 요청을 제대로 처리하지 못하면, 공격자는 서버의 중요한 파일에 접근할 수 있다. %2e와 같은 URL 인코딩된 문자열은 이런 공격을 우회하기 위해 사용될 수 있기 때문에, 기본적으로 차단된다.
이러한 공격을 디렉토리 트래버셜(Directory Traversal) 공격이라고 한다.

2. 허용되지 않은 HTTP 메서드
HTTP 메서드는 웹 애플리케이션과 상호작용하는 방법을 정의한다. Spring Security는 기본적으로 일부 메서드를 허용하지 않는다. 그 이유는 이 메서드들이 특정한 보안 취약점을 유발할 수 있기 때문이다.

  • PURGE 메서드
    PURGE 메서드는 주로 캐시 서버에서 특정 항목을 제거하는 데 사용된다. 일반적인 웹 애플리케이션에서 잘 사용되지 않으며, 만약 허용된다면 캐시 일관성을 해칠 수 있다.

  • TRACE 메서드
    TRACE 메서드는 요청이 서버에 도달할 때까지의 경로를 추적하는 데 사용된다. 이는 디버깅에 유용할 수 있지만, 클라이언트가 요청에 포함된 헤더 정보를 확인할 수 있게 한다. 이는 XSS(Cross-Site Scripting) 공격을 유발할 수 있기 때문에 보안상의 이유로 차단된다.


시큐리티의 기본 구현체인 StrictHttpFirewall 에서는, 악성 URL로 인한 사이드 이펙트를 최소화하기 위해 위와 같은 수많은 문자들이 포함된 URL은 아예 거부하고 있다.
이미지를 보면 필자가 경험한 "%2e"을 거부하는 것을 알 수 있다.

HttpFirewall 설정 변경

만약 %2e와 같은 마침표를 허용하고 싶다면 아래와 같은 방법을 사용할 수 있다.

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public HttpFirewall customHttpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setAllowUrlEncodedPeriod(true); // URL 인코딩된 마침표 허용
        return firewall;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .httpFirewall(customHttpFirewall());
    }
}

이 설정을 통해 URL 인코딩된 마침표를 허용하여 RequestRejectedException 예외를 방지할 수 있다.

HTTP Method 커스텀은?
Spring은 아래의 코드처럼 허용한 Method의 요청을 받기 때문에 커스텀을 통해 HttpFirewall을 수정하더라도 HTTP Method가 일치하지 않는다면 405 Error를 호출한다.

@GetMapping("/test")
public Response<TestResponse> test() {
	Response.success(testService.test());
}

공식문서
https://docs.spring.io/spring-security/reference/servlet/exploits/firewall.html

profile
매일은 아니더라도 꾸준히 올리자는 마음으로 시작하는 개발블로그😎

0개의 댓글