Spring/Spring Security

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

noahkim_ 2023. 10. 14. 02:54

1. HttpFirewall

  • Spring Security의 FilterChainProxy에 전달되는 요청을 검사하고, 위험한 요청을 차단하는 매커니즘
  • 서블릿 컨테이너마다 URL 해석 방식이 다르므로, 아래와 같은 경우에 보안 문제가 발생할 수 있음

 

역할

  • HTTP 요청이 보안 필터 체인에 도달하기 전에 요청을 검사하고, 필요한 경우 수정하는 역할을 합니다.
구분 설명 예시 / 차단 대상
정규화 URL 경로에서 위험한 문자나 패턴을 제거하여 안전하게 변환
/a/../b,
//multiple//slashes,
/path;param=value 등
요청 검증 악의적인 요청을 식별하고 차단
; 세미콜론이 포함된 경로
비정상 쿼리 스트링
허용되지 않은 HTTP 메서드
HTTP 응답 분할 방지 악의적 응답 조작이 일어나지 않도록 차단
(응답 헤더에 개행 문자 등 삽입)
\r, \n 포함된 헤더
→ 공격자가 응답을 조작하여 스크립트 삽입 가능

 

StrictHttpFirewall (기본 구현체)

  • 기본적으로 많은 종류의 잠재적 위험 요소를 차단합니다.
차단 요소 설명 예시
; 세미콜론 파라미터 경로에 세미콜론(;)이 포함된 파라미터
URL 우회 또는 세션 ID 조작 등에 사용될 수 있음
/secure;jsessionid=abc/file.html
../ 경로 역참조 상위 디렉토리로 이동하는 경로.
디렉토리 탈출(Path Traversal) 공격에 악용될 수 있음
/images/../../admin/config.yaml
// 중복 슬래시 두 개 이상의 연속된 슬래시
경로 매핑 우회 시도 가능
/api//admin
/user///info
❌ 허용되지 않은 HTTP 메서드 Spring Security에서 허용하지 않는 메서드
보안상 위험 요소 있음
CONNECT / HTTP/1.1
TRACE / HTTP/1.1
❗ ISO-8859-1에 없는 문자 포함 헤더 HTTP 헤더에 표준 문자셋에 없는 문자 사용 시.
파싱 오류나 응답 조작 가능성 있음
특수 문자 포함
(User-Agent: iPhone Xʀ 등)

 

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로 구문 분석하는 것을 고려할 수 있습니다.

 

 

 

출처