Quick answer
HTTP request smuggling remains the highest-ROI bug in 2026 against complex stacks (CDN + WAF + origin). The four variants that pay: CL.TE (classic), TE.CL (inverted classic), H2.CL (HTTP/2 downgrade with a custom Content-Length), and the recent single-packet H2 desync that defeats serverless load balancers like Cloudflare Workers. When the frontend and backend interpret differently where a request ends, the attacker smuggles a second one inside the first → ATO, cache poisoning, internal access. Detection: smuggler.py + Burp HTTP Request Smuggler + timing-based oracles.
1. The mental model
[Cliente] → [Frontend (CDN/LB/WAF)] → [Backend (origin)]
↑ ↑
CL: 13 TE: chunked
"parser cree termina aquí" "parser cree termina más allá"
When the frontend says "this request ends at byte 13" and the backend says "this one ends at byte 50", bytes 14-50 get prepended to the next request that reaches the backend on the same TCP/TLS connection.
That "next request" belongs to another user (backend connections are shared). The attacker controls what gets prepended to other people's requests. That's account takeover, cache poisoning, internal endpoint access.
2. The four main variants
| Variant | Frontend uses | Backend uses | When it applies |
|---|---|---|---|
| CL.TE | Content-Length | Transfer-Encoding: chunked | Older frontend, modern backend |
| TE.CL | Transfer-Encoding: chunked | Content-Length | Modern frontend, older backend |
| TE.TE | TE with obfuscation | standard TE | Both support TE but one fails with a variant |
| H2.CL / H2.TE | HTTP/2 framing | HTTP/1.1 with CL/TE | Frontend H2 downgrade to H1 at the origin |
3. Classic CL.TE
POST / HTTP/1.1
Host: target.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
- Frontend reads
Content-Length: 13→ consumes 13 bytes (0\r\n\r\nSMUGGLED), forwards to the backend. - Backend reads
Transfer-Encoding: chunked→ the first chunk is0(empty, end of body) → consumes only0\r\n\r\n→ the wordSMUGGLEDstays in the buffer. - The next normal request from the next user gets concatenated with
SMUGGLEDin front →SMUGGLEDGET / HTTP/1.1...→ corrupted, or usable as a prefix injection.
Timing detection
POST / HTTP/1.1
Host: target.com
Content-Length: 4
Transfer-Encoding: chunked
1
A
X
If the response takes a long time (a timeout waiting for bytes that never arrive) → CL.TE. The backend interprets TE, waits for the already-consumed 1-byte chunk + a next one that never comes.
4. Classic TE.CL
POST / HTTP/1.1
Host: target.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
- Frontend reads TE → first chunk of 8 bytes (
SMUGGLED), then0\r\n\r\n→ request ends, everything forwarded to the backend. - Backend reads
Content-Length: 3→ consumes only8\r\n(3 bytes) → the rest (SMUGGLED\r\n0\r\n\r\n) stays in the buffer → prepended to the next request.
Timing detection
POST / HTTP/1.1
Host: target.com
Content-Length: 6
Transfer-Encoding: chunked
0
X
The backend reads 6 bytes with CL → takes 0\r\n\r\nX → immediate response. But the X stays in the buffer → next request corrupted (invalid paths).
Keep reading the full chain
The remaining part includes the step-by-step PoC, exploitation code and the full chain that led to impact. Available to subscribers.
Practice this in a lab
Http Request Smuggling
Keep learning · free account
Save your progress, unlock advanced payloads and rank your flags.