HTTP Request Smuggling
When a request passes through a front-end (proxy, CDN, load balancer) before reaching the back-end, both must agree on where one request ends and the next begins. If they disagree on how to interpret the body length, the attacker “smuggles” part of their request into the start of the next user’s request. That’s request smuggling: poisoning the shared request queue.
flowchart LR
A[Attacker] -->|"ambiguous request (CL.TE / TE.CL)"| F[Front-end]
F -->|"sees it as one"| B[Back-end]
B -. "back-end splits it in two (desync)" .-> V["Prefix injected into the<br/>next victim's request"]
Threat model
Section titled “Threat model”The bug isn’t in one machine, it’s in the disagreement between two. The front forwards over a keep-alive connection to the back, and if one counts the body by Content-Length and the other by Transfer-Encoding: chunked, a carefully malformed request is split differently on each side. The leftover part of the request is prepended to the victim’s request on that same connection.
Classic variants
Section titled “Classic variants”By which header each end prioritizes:
- CL.TE: the front uses
Content-Length, the back usesTransfer-Encoding. - TE.CL: the front uses
Transfer-Encoding, the back usesContent-Length. - TE.TE: both support
Transfer-Encodingbut one can be obfuscated into ignoring it (Transfer-Encoding: xchunked, spaces, duplicate header).
POST / HTTP/1.1Host: targetContent-Length: 6Transfer-Encoding: chunked
0
GIf the back prioritizes chunked, it sees the request ending at 0\r\n\r\n and the G stays at the start of the buffer → prepended to the next request (GPOST ...).
Red Team
Section titled “Red Team”Discovery
Section titled “Discovery”- Timing detection: a malformed CL.TE/TE.CL request makes the back wait for bytes that never arrive → measurable delay. Burp’s technique.
- Try
Transfer-Encodingobfuscations: space before:, tab,\nas separator, double TE, oddly-cased value. - HTTP/2 → HTTP/1.1 downgrade: the front speaks H2 and translates to H1 to the back; inconsistent
Content-Length/chunkedor headers H2 allows and H1 doesn’t (H2.CL, H2.TE, CRLF in values).
By hand / chained impact
Section titled “By hand / chained impact”Once the desync is confirmed:
- Steal other users’ requests: smuggle a prefix that captures the next request (with its cookie) and reflects it to an endpoint you control.
- Bypass front-end controls: the front filters
/admin, but you smuggle a request to/adminthe front doesn’t inspect. - Response queue poisoning: misalign requests and responses → a user gets another’s response.
- Chained cache poisoning: smuggling + cache poisons responses for everyone.
- Turn XSS/open redirect into something that hits victims with no interaction.
# conceptual CL.TE: prefix left queued for the victimPOST / HTTP/1.1Host: targetContent-Length: 4Transfer-Encoding: chunked
0
GET /admin HTTP/1.1X-Ignore: X- Burp Suite — HTTP Request Smuggler extension (James Kettle): timing detection, desync probe, H2 downgrade.
- Turbo Intruder — to send requests with fine framing control.
- h2csmuggler — for desync via HTTP/2 cleartext upgrade.
Impact
Section titled “Impact”Hijacking of other users’ sessions, bypass of front-end auth/authZ, mass cache poisoning, exfiltration of in-transit credentials.
Blue Team
Section titled “Blue Team”Detection
Section titled “Detection”- Requests with both
Content-LengthandTransfer-Encoding. - Obfuscated
Transfer-Encoding(spaces, non-standard values, duplicated). - Responses that don’t match the client’s request; users seeing others’ data.
Telemetry
Section titled “Telemetry”Log raw framing headers; alert on simultaneous CL+TE and on malformed TE.
Hardening
Section titled “Hardening”- Use HTTP/2 end-to-end with no downgrade to HTTP/1.1 on the internal hop (eliminates the whole class when H2 is kept).
- Normalize/reject at the front any request with
CL+TEor ambiguousTE; a single interpretation across the whole chain. - Front and back with the same server/version and parsing config; disable back-end connection reuse if not safe.
- Reject duplicate headers and values not conforming to RFC 7230.
- Keep WAF/reverse-proxy updated (many smuggling fixes are config/version).
Response
Section titled “Response”Invalidate cache, rotate affected sessions, patch/align front and back parsing, disable keep-alive to the back if needed.
CVEs and real-world cases
Section titled “CVEs and real-world cases”- James Kettle — “HTTP Desync Attacks” (2019) and “HTTP/2” (2021) — foundational research; hit major CDNs and thousands of sites.
- CVE-2019-18277 (HAProxy), CVE-2021-33193 (Apache mod_http2) — smuggling in popular servers/proxies.
- Netflix, PayPal and others — critical desync disclosed in James Kettle’s HTTP Request Smuggling research (PortSwigger).
- Multiple advisories from Varnish, Squid, nginx, and load balancers over framing discrepancies.
Testing checklist
Section titled “Testing checklist”- Does the front forward to the back over keep-alive? (prerequisite)
- Does timing detection (CL.TE / TE.CL) show desync?
- Does obfuscating
Transfer-Encodingchange interpretation? (TE.TE) - Is there an HTTP/2→HTTP/1.1 downgrade with inconsistent CL/TE? (H2.CL/H2.TE)
- Can a request be prepended to another user’s?
- Are front-end controls (/admin) bypassed via smuggling?
- Is CL+TE framing rejected or normalized at the front?