HTTP request smuggling abuses a disagreement between two servers in a chain, typically a front-end proxy or load balancer and a back-end server, about how to determine the length of an HTTP request. By crafting a request with conflicting Content-Length and Transfer-Encoding headers, an attacker can make one server see one request while the other sees two, smuggling a hidden request that gets prepended to the next user's traffic. Consequences include request hijacking, web cache poisoning, and bypassing front-end security controls.
What HTTP request smuggling is
HTTP lets a server determine a request body's length two ways: the Content-Length header, or Transfer-Encoding: chunked. When a request contains both, the specification says one should win, but front-end and back-end servers do not always agree on which.
That disagreement is the vulnerability. If the front-end uses one header to decide where the request ends and the back-end uses the other, part of the attacker's request is left in the back-end's buffer. It then gets attached to the front of the next request that arrives on that connection, a request belonging to another user. The attacker has effectively injected content into someone else's session.
The abuse and impact
Testers craft a request that the two servers parse differently. Shown for defensive context:
- CL.TE: the front-end honors
Content-Length, the back-end honorsTransfer-Encoding: chunked. The attacker hides a request after a zero-length chunk terminator. - TE.CL: the reverse, the front-end honors chunked encoding and the back-end honors
Content-Length. - TE.TE: both support chunked, but one can be tricked into ignoring it by obfuscating the header, for example
Transfer-Encoding: xchunked.
Impact is high: capturing other users' requests and session tokens, poisoning a shared cache so every visitor is served attacker content, and bypassing front-end access controls to reach restricted back-end paths. These chained outcomes make it a priority target in web app pentest engagements against proxied architectures.
How to defend
Remove the ambiguity so both servers always agree:
- Prefer HTTP/2 end to end and do not downgrade to HTTP/1.1 at the back-end, since HTTP/2 carries length unambiguously.
- Reject ambiguous requests: the front-end should refuse any request that contains both
Content-LengthandTransfer-Encoding, and normalize headers before forwarding. - Use the same server software and configuration for front-end and back-end where possible so parsing matches.
- Disable connection reuse to the back-end if the risk cannot otherwise be removed, so a smuggled fragment cannot attach to another user's request.
Keep proxies and web servers patched, since specific parsing bugs are fixed over time.
References
- [1]PortSwigger: HTTP request smuggling(PortSwigger)
- [2]OWASP: HTTP Request Smuggling(OWASP)
- [3]MITRE ATT&CK: Exploit Public-Facing Application (T1190)(MITRE)