HTTP Request Smuggling
HTTP request smuggling exploits discrepancies between how a front-end proxy and a back-end server parse HTTP request boundaries. The result is that you can “smuggle” a hidden request that gets prepended to another user’s request.
How It Works
Modern web infrastructure uses a front-end server (load balancer, CDN, reverse proxy) that forwards requests to a back-end. HTTP/1.1 has two ways to specify request body length: Content-Length and Transfer-Encoding: chunked. When the two servers disagree on which takes precedence, you can inject data that the back-end interprets as the beginning of the next request.
CL.TE — Front-end uses Content-Length, Back-end uses Transfer-Encoding
The front-end reads the full Content-Length. The back-end reads until the chunked terminator 0\r\n\r\n, leaving your smuggled prefix in the back-end’s buffer.
|
The front-end sees Content-Length=13, forwards 13 bytes (0\r\n\r\nSMUGGLED). The back-end reads the chunk (size 0 = terminator), and SMUGGLED remains in the buffer — prepended to the next request.
Confirm CL.TE with timing
|
If there’s a ~10 second delay (server waiting for next chunk), CL.TE is confirmed.
TE.CL — Front-end uses Transfer-Encoding, Back-end uses Content-Length
|
The front-end reads the chunked body (8 bytes + terminator), forwards everything. The back-end reads Content-Length=3, takes 8\r\n as body, leaving SMUGGLED\r\n0\r\n\r\n in the buffer.
Confirm TE.CL with timing
|
Back-end reads Content-Length=6 (0\r\n\r\nX), then waits for 1 more byte that never comes → timeout = TE.CL confirmed.
TE.TE — Both servers support TE, but one can be obfuscated
Both servers support Transfer-Encoding, but you can obfuscate it so one ignores it:
|
Exploits
Bypass front-end security controls
Front-end blocks access to /admin. Back-end trusts front-end to enforce this. Smuggle a request to /admin:
|
The GET /admin is smuggled into the back-end’s buffer and processed as though it came from an internal source (trusted by the back-end).
Capture other users’ requests
|
The next victim’s request is appended as the body of your POST /capture request, and the search parameter captures it (e.g., if /capture is a search endpoint that logs queries).
Session hijacking via request poisoning
|
HTTP/2 Request Smuggling
HTTP/2 has explicit framing — no ambiguity in the protocol itself. But when a front-end downgrades to HTTP/1 for the back-end, inconsistencies arise.
H2.CL
|
H2.TE (header injection)
|
Injecting TE into an HTTP/2 request that gets downgraded.
Detection with Burp
Burp Suite → Extensions → HTTP Request Smuggler
|
Manual detection — look for:
- Timing differences between two similar requests
- 400 errors from the back-end when smuggling breaks parsing
- Differential responses (victim’s request arriving with your prefix)
Remediation
- Use HTTP/2 end-to-end (no downgrade to HTTP/1).
- If using HTTP/1, configure both servers to use the same parsing priority (prefer TE over CL).
- Normalize ambiguous requests at the front-end — reject requests with both Content-Length and Transfer-Encoding.
- Use a WAF or RASP that understands HTTP parsing.
Discussion
Leave a comment · All fields required · No spam
No comments yet. Be the first.