HTTP Request Smuggling
When Two Servers Disagree
Modern web architectures almost always place a front-end (a load balancer, CDN, or reverse proxy) in front of a back-end application server. Both must parse every incoming HTTP request and agree on where one request ends and the next begins. HTTP request smuggling exploits the cases where they disagree.
The Root Cause: Conflicting Lengths
HTTP/1.1 offers two ways to specify a request body's length:
Content-Length(CL): the body is exactly N bytes.Transfer-Encoding: chunked(TE): the body is sent in chunks, terminated by a zero-length chunk.
If a request contains both headers, or if one server honors Content-Length while the other honors Transfer-Encoding, the two servers compute different message boundaries. The front-end forwards what it thinks is one request; the back-end sees the leftover bytes as the start of a second request. That smuggled prefix is prepended to the next user's request—which makes request smuggling a request poisoning attack, affecting other users, not just the attacker.
CL.TE and TE.CL
- CL.TE: the front-end uses
Content-Length, the back-end usesTransfer-Encoding. The attacker sends a body that the front-end considers complete but the back-end considers to have a chunked remainder, smuggling a second request. - TE.CL: the reverse—the front-end honors
Transfer-Encoding, the back-endContent-Length. - TE.TE: both honor TE, but one can be tricked into ignoring it with an obfuscated header (e.g.,
Transfer-Encoding: xchunked), collapsing back into a CL/TE disagreement.
What Attackers Do With It
Smuggled requests are invisible to the front-end's logging, rate limiting, and authentication. Attackers use them to:
- Bypass access controls: reach an admin endpoint that the front-end would block.
- Poison the cache: trick the front-end into caching a response to a smuggled request, serving it to every subsequent visitor.
- Hijack other users' requests: capture the credentials or cookies that other users' requests carry into the desynchronized connection.
- Reflected XSS at scale: make the front-end attribute a malicious response to a victim's request.
Detecting It
Smuggling is timing-sensitive and backend-dependent, so testing is delicate. Tools like Burp Suite's "HTTP Request Smuggler" extension automate the crafted payloads and carefully detect the desync without disrupting production. Safe testing requires sending requests that cause a harmless, detectable difference (e.g., a 404 versus a 400 on the following request) rather than actually poisoning other users.
Defenses
- Disable
Transfer-Encodingre-chunking ambiguity: normalize requests at the edge—strip or reject requests containing both CL and TE. - Use HTTP/2 end-to-end: HTTP/2 uses a single, unambiguous length framing and eliminates the CL/TE ambiguity, though downgrade paths to HTTP/1.1 at the back-end can reintroduce it.
- Reject malformed requests: treat any request with conflicting or obfuscated length headers as hostile.
- Keep proxies patched: many smuggling bugs live in the front-end's parser; vendors ship fixes.
- Consistent parsing: ideally the same server software parses at both layers.
Request smuggling is a powerful reminder that security depends on agreement. When two systems interpret the same bytes differently, an attacker can live in the gap between them.