Skip to content
Field Details
Platform PortSwigger Web Security Academy
Type HTTP Request Smuggling — CL.0, Admin Bypass
Difficulty Expert
Objective Exploit a CL.0 vulnerability on a static file endpoint to reach /admin and delete carlos

CL.0 Request Smuggling

Navigating to /admin:

Screenshot

Path /admin is blocked — front-end is blocking it. Same goal as before, different mechanism.

CL.0 is a variant where the back-end ignores the Content-Length header on certain endpoints — typically static file endpoints. When CL is ignored, the server treats the body as zero-length and closes the request immediately. Anything in the body stays in the TCP buffer as the beginning of the next request. No HTTP/2, no Transfer-Encoding, no chunked encoding — just a Content-Length the server chooses to ignore.

From Proxy → HTTP History, two requests get sent to Repeater and grouped together. First is a POST to /, second is a normal GET to /:

POST / HTTP/1.1
Host: 0a4d00f8042f4f44808c581d001000f6.web-security-academy.net
Content-Length: 32

GET /miku HTTP/1.1
Teto: teto
Screenshot

Sending the group — the second request doesn't return 404. No desync on /. The back-end is processing Content-Length correctly on the root. Static file endpoints are the usual culprits, so we try the same payload pointing the POST at a static resource:

POST /resources/images/blog.svg HTTP/1.1
Host: 0a4d00f8042f4f44808c581d001000f6.web-security-academy.net
Content-Length: 32

GET /miku HTTP/1.1
Teto: teto
Screenshot
Screenshot

The second request returns 404 Not Found: /miku. The static file endpoint ignores Content-Length, the body bytes float into the buffer, and the next request gets our smuggled GET /miku prepended to it. Desync confirmed.

Worth noting: changing the filename to something nonexistent (/resources/images/teto) still triggers the CL.0 behavior — the server applies the same Content-Length-ignoring logic to the entire /resources/ path, not just files that exist.

Updating the smuggled request to target /admin:

POST /resources/images/teto HTTP/1.1
Host: 0a4d00f8042f4f44808c581d001000f6.web-security-academy.net
Content-Length: 33

GET /admin HTTP/1.1
Teto: teto
Screenshot

The second request in the group returns the admin panel — the front-end's block on /admin doesn't apply because the request reaches the back-end directly via the smuggled prefix.

Updating the smuggled path to /admin/delete?username=carlos and sending the group — the normal request returns 302 Found:

Screenshot

we delete carlos and the lab solved :P

Resources