TE.CL HTTP Request Smuggling: Proving a Front-End Desync Safely
TE.CL is the mirror image hunters sometimes overlook. The front-end proxy decodes chunked framing; the origin ignores it and reads the body according to Content-Length. A zero chunk can end the request for the edge while the origin keeps consuming bytes.
One misplaced digit can wedge a worker or contaminate a shared queue. Work on a program that explicitly permits request-smuggling tests, throttle down, and keep your evidence tied to accounts you own.
Recognize the parser split
A compact probe sends a valid chunked body whose declared content length asks the origin for more:
POST / HTTP/1.1
Host: target.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
0
X
The front end sees the 0 chunk and forwards a completed request. A CL-only back end expects four body bytes and may wait. Exact line endings matter: Burp Repeater's inspector and visible newline mode save plenty of false starts.
A timeout by itself is weak evidence. Compare several controls: remove TE, correct CL, change the endpoint, and send over a new connection. If every malformed request takes the same time, you may only be hitting generic body validation. A real desync should follow the framing changes.
Controlled queue poisoning
Once timing looks consistent, stop fuzzing and prove state. Craft a body that ends for the edge but leaves bytes the origin interprets as a prefix for your next request. Then send that follow-up yourself. A changed path, injected header, or predictable 404 on the second response is enough.
Keep the prefix harmless. GET /smuggle-canary-7f3 HTTP/1.1 is better than an admin route. If the target requires authentication, use two sessions you own and show the canary crossing only between them. Never wait for production users to supply the victim request.
Common wrinkles include:
- The CDN accepts TE but strips it before the origin
- A web application firewall rewrites CL after inspecting the decoded body
- The public listener speaks HTTP/2, then creates HTTP/1.1 requests upstream
- Connection affinity prevents your second socket from reaching the poisoned back-end connection
- The app closes connections after every response, removing practical exploitability
Those details are not footnotes. They decide whether the issue is a reliable attack or a laboratory curiosity.
Report the boundary, not just the payload
Include the raw bytes or Burp request with CRLF preserved, response timings against controls, connection settings, and one controlled follow-up. Explain which hop appears TE-aware and which appears CL-aware. If you only infer the architecture, label it as inference.
Impact can rise when the prefix bypasses a front-end ACL, poisons cache keys, or captures a response intended for your second test account. Do not promise account takeover from a 10-second delay. Triage teams have seen too many scanner-only smuggling reports.
Fixes should reject ambiguous requests, enforce identical parsing across every hop, and disable reuse when a malformed body appears. HTTP/2 end to end removes many classic framing ambiguities, though downgrade paths still need review. This weakness maps to CWE-444. PortSwigger's TE.CL lab gives a reproducible model, while the OWASP Web Security Testing Guide supplies the broader testing discipline.