CL.0 request smuggling

3 min read Medium PortSwigger
HTTP request smuggling
Contents

On this page

The lab

here is how portswigger describes it

This lab is vulnerable to CL.0 request smuggling attacks. The back-end server ignores the Content-Length header on requests to some endpoints.

To solve the lab, identify a vulnerable endpoint, smuggle a request to the back-end to access to the admin panel at /admin, then delete the user carlos.

what cl.0 is?#

the naming follows the same pattern as the earlier labs, the letters say how each server reads the body length. cl.0 means the front end reads the Content-Length normally, but the back end behaves as though the Content-Length were 0, that is, it ignores the header and assumes the request has no body.

this usually happens on endpoints that were never expected to receive a body, static files, redirects, and similar, where the back end just does not bother reading one. the effect is the same desync we have seen throughout the series. the front end, trusting Content-Length, forwards our whole body to the back end. the back end, ignoring Content-Length, thinks our request ended at the headers, so it treats the body we sent as the start of a separate request on the connection. our body becomes a smuggled request.

because the trick only works on endpoints where the back end ignores the body, the first job is to find such an endpoint, and the second is to point our real request at it while hiding the admin request in the body.

Step 1 - Set up two Requests on one connection#

we intercept a request, send it to repeater, and clone it so we have two identical requests. we add both to a new tab group, because cl.0 needs the smuggled bytes to attach to a following request, so the two have to travel down the same connection one after the other.

1111

Step 2 - Build the smuggle on the first request#

we take the first request, convert it to a POST, and put a smuggled request in its body.

HTTP
POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Cookie: session=your-session-cookie
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: correct-length

GET /404 HTTP/1.1
Foo: x
2222

a couple of details. Content-Length has to be the exact byte count of the body, the smuggled GET /404 block, and burp can compute that correct value for us. the Connection header is set to keep-alive so the connection stays open for the second request to follow, rather than closing after the first. and the smuggled request points at /404, a dead path, so if it runs we will see a clear 404.

then, using the drop down next to the send button, we set the send mode to send group in sequence on a single connection, so both requests share one connection.

Step 3 - Hunt for a vulnerable endpoint#

we send the sequence and read the second response, and that response is the test.

3333

if the second request gets its normal response, this endpoint reads the body properly and is not vulnerable. but if the second response is the 404 we expected from our smuggled GET /404, then the back end ignored our Content-Length, treated our body as a separate request, and answered it, which is cl.0 confirmed. we are free to try any endpoint in the application on the first request until one behaves this way.

4444

a static resource path turns out to be vulnerable, the kind of endpoint that serves a file and never expects a body, so it ignores Content-Length.

Step 4 - Smuggle the delete and solve#

now we point the real request at that vulnerable static endpoint and put the delete request for carlos in the body.

HTTP
POST /resources/images/blog.svg HTTP/1.1
Host: your-lab-id.web-security-academy.net
Cookie: session=your-session-cookie
Connection: keep-alive
Content-Length: correct-length

GET /admin/delete?username=carlos HTTP/1.1
Foo: x
5555

the front end forwards the whole thing to the vulnerable endpoint, the back end ignores the Content-Length and treats the body as a new request, so the smuggled GET /admin/delete?username=carlos runs on the back end and carlos is deleted. 6666

with this, we solved the lab!