Netty HTTP 헤더 검증 비활성화로 인한 HTTP 요청/응답 분할 (CRLF Injection)

HTTP Request/Response Splitting

설명

Netty에서 DefaultHttpHeaders, DefaultHttpRequest, DefaultHttpResponse 생성 시 validateHeaders 옵션을 false로 두면 헤더 값에 포함된 CR/LF(\r\n)가 차단되지 않습니다. 이 상태에서 사용자 입력이 헤더로 들어가면 공격자가 \r\n을 이용해 헤더 경계를 탈출하여 추가 헤더나 별도의 응답/요청을 주입할 수 있어 HTTP Request/Response Splitting 취약점이 발생합니다. 공격자는 URL 인코딩된 %0d%0a(=\r\n)를 삽입해 Set-Cookie, Location 같은 헤더를 추가하거나, 프록시/캐시를 속여 악성 응답을 다른 사용자에게 전달하거나, 동일 연결에서 두 번째 요청을 주입하는 등으로 악용할 수 있습니다.

잠재적 영향

  • XSS 유발: 응답 분할을 통해 임의의 스크립트나 콘텐츠를 주입하여 브라우저에서 실행되게 만들 수 있음.

  • 캐시 오염(Cache Poisoning): 추가/변조된 헤더로 CDN/프록시 캐시를 오염시켜 다른 사용자에게 악성 응답이 제공될 수 있음.

  • 쿠키/헤더 변조: Set-Cookie, Location, Content-Type 등 중요한 헤더를 주입·변조하여 세션 탈취, 리다이렉트 유도 가능.

  • 내부 요청 유도(SSRF 유사): 요청 분할로 같은 TCP 연결에 2번째 요청을 삽입해 백엔드/내부 서비스로 임의 요청을 보내게 만들 수 있음.

  • 로깅 교란 및 탐지 회피: CR/LF로 로그 라인을 깨뜨려 보안 모니터링을 우회하거나 분석을 어렵게 만듦.

해결 방법

  • Netty 헤더 검증 활성화 유지: 기본 생성자 또는 true 인자를 사용

    • new DefaultHttpHeaders() 또는 new DefaultHttpHeaders(true)

    • new DefaultHttpRequest(version, method, uri) 또는 (.., true)

    • new DefaultHttpResponse(version, status) 또는 (.., true)

  • 사용자 입력 검증/정규화: 헤더에 넣기 전 CR(\r), LF(\n), 콜론(:) 제거 또는 인코딩, 길이 제한, 화이트리스트 패턴 적용.

  • 프레임워크 기본 검증 우회 금지: validateHeaders=false 설정을 사용하지 말고, 필요한 경우 추가 애플리케이션 레벨 검증만 보강.

  • 헤더 이름은 상수로 관리: 사용자 입력을 헤더 이름으로 사용하지 말 것.

  • 업스트림 보완: 리버스 프록시/로드밸런서에서 CRLF 포함 요청 차단, 헤더 정규화 옵션 사용.

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: validateHeaders=false로 생성한 응답은 Netty의 CR/LF 차단이 비활성화되어, 사용자 입력에 포함된 \r\n이 그대로 헤더에 들어갑니다. 이로 인해 공격자는 헤더 경계를 탈출하여 추가 헤더(예: Set-Cookie)나 별도의 응답/요청을 주입할 수 있어 Request/Response Splitting이 발생합니다.

  • 안전한 코드: 기본 생성자(또는 true 인자)를 사용해 헤더 검증을 활성화하고, 헤더에 넣기 전 입력값에서 CR, LF, 콜론을 제거하여 헤더 경계 파괴를 예방합니다. 이렇게 하면 Netty의 내장 검증과 애플리케이션 검증이 함께 동작하여 CRLF 기반 주입 및 응답/요청 분할 공격을 차단합니다.

참조

Last updated