Spring/Spring Security

[Spring Security] 5-4. 보안: HttpFirewall

noahkim_ 2023. 10. 14. 02:54

1. HttpFirewall

  • Spring Security의 FilterChainProxy가 들어오는 HTTP 요청을 검사하고, 보안상 위험한 요청을 차단하는 방화벽
  • ✅ 서블릿 컨테이너마다 세미콜론, 중복 슬래시, 인코딩 문자 등 해석하는 방식이 다름
  • ⚠️ 이 차이를 이용하면 보안 필터가 검사한 경로와 실제 애플리케이션이 처리한 경로가 달라 규칙을 우회할 수 있음

 

역할

구분 설명 검사 대상
요청 검증 악의적이거나 모호한 요청을 식별하고 거부 URL, HTTP 메서드, 헤더, 파라미터, Host
경로 일관성 확보 보안 경로 매칭에 사용할 일관된 요청 경로 제공 servletPath, pathInfo
응답 보호 응답 헤더에 개행 문자가 삽입되는 것을 차단 \r, \n이 포함된 응답 헤더
필터 체인 우회 방지 컨테이너별 URL 해석 차이를 이용한 인가 우회 방지 세미콜론, 중복 슬래시, 인코딩 문자 등

 

StrictHttpFirewall

  • SpringSecurity Servlet 환경에서 자동으로 적용되는 HttpFirewall 기본 구현체
  • ✅ 의심스러운 요청을 정규화하여 허용하기보다 RequestRejectedException을 발생시켜 요청을 거부함
차단 요소 예시 차단 이유
정규화되지 않은 URL /a/../admin, /api//admin 경로 해석 차이를 이용한 인가 우회 방지
세미콜론 포함 경로 /secure;jsessionid=abc 경로 파라미터나 세션 ID를 이용한 우회 방지
위험한 인코딩 문자 %2F, %00, \ 디코딩 차이와 경로 우회 방지
허용되지 않은 HTTP 메서드 TRACE, CONNECT XST, HTTP Method 우회 공격 방지
비정상 헤더·파라미터 \r, \n, 제어 문자 포함 Header Injection, 파싱 오류 방지
비정상 Host Host: evil.example Host Header Injection 방지

 

2. 커스터마이징

설정) 세미콜론 허용

더보기
@Bean
public StrictHttpFirewall httpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowSemicolon(true);
    return firewall;
}
  • URL에 세미콜론을 허용할 수 있습니다.

 

설정) HTTP 메소드 허용 목록

더보기
@Bean
public StrictHttpFirewall httpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST"));
    return firewall;
}
  • 공격을 방지하기 위해 허용되는 HTTP 메소드 목록 설정 가능 (XST, HTTP Verb Tampering 등)
  • setAllowedHttpMethods 사용하여 허용되는 HTTP 메소드를 GET 및 POST로만 설정할 수 있습니다.
  • 기본적으로 모든 메소드가 허용됨

 

설정) 헤더 및 파라미터 이름 및 값 검증

더보기
@Bean
public StrictHttpFirewall httpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowedHeaderNames((header) -> true);
    firewall.setAllowedHeaderValues((header) -> true);
    firewall.setAllowedParameterNames((parameter) -> true);
    return firewall;
}

 

설정) 특정 값 허용

더보기
@Bean
public StrictHttpFirewall httpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    Pattern allowed = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*");
    Pattern userAgent = ...;
    firewall.setAllowedHeaderValues((header) -> allowed.matcher(header).matches() || userAgent.matcher(header).matches());
    return firewall;
}

예를 들어 iPhone Xʀ는 ISO-8859-1 문자 집합에 포함되지 않는 문자를 포함하는 User-Agent를 사용합니다.

  • 이로 인해 일부 애플리케이션 서버는 이 값을 두 개의 별도 문자로 구문 분석합니다.
  • 이를 처리하기 위해 setAllowedHeaderValues 메소드를 사용하여 특정 User-Agent를 허용할 수 있습니다.

 

설정) 헤더 값을 UTF-8로 구문 분석

더보기
firewall.setAllowedHeaderValues((header) -> {
    String parsed = new String(header.getBytes(ISO_8859_1), UTF_8);
    return allowed.matcher(parsed).matches();
});
  • 헤더 값의 경우, 검증 시점에 이를 UTF-8로 구문 분석하는 것을 고려할 수 있습니다.

 

출처