Description
HTTP request smuggling (HRS) exploits ambiguity in how the Content-Length and Transfer-Encoding: chunked headers are parsed by different HTTP/1.1 components in a forwarding chain. When a frontend proxy (load balancer, CDN, WAF) and a backend server disagree about where one HTTP request ends and the next begins, an attacker can "smuggle" a partial request prefix into the backend's request buffer—where it is prepended to the next legitimate user's request, effectively hijacking it.
CWE-444 (Inconsistent Interpretation of HTTP Requests) is the direct classification. A04:2021 Insecure Design applies because the vulnerability arises from architectural decisions about request forwarding and header handling that create systemic ambiguity. The attack does not require any injection vulnerability in application logic—it exploits protocol-level inconsistencies in the infrastructure.
HRS can be used to bypass WAFs and security controls (the frontend WAF inspects what it believes is a complete, benign request while the backend receives a malicious payload prepended to the next request), poison shared caches, perform cross-user attacks by capturing other users' requests, and exploit otherwise-inaccessible internal endpoints.
How It Works
There are three primary HRS variants based on which component processes which header:
CL.TE (frontend uses Content-Length, backend uses Transfer-Encoding):
POST / HTTP/1.1
Host: example.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
The frontend reads 13 bytes (the full body). The backend, processing chunked encoding, reads a zero-length chunk (the 0\r\n\r\n) and considers the request complete—leaving SMUGGLED in its buffer to be prepended to the next request.
TE.CL (frontend uses Transfer-Encoding, backend uses Content-Length):
POST / HTTP/1.1
Host: example.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
Practical bypass example — smuggling a request to a restricted internal endpoint:
POST /public-endpoint HTTP/1.1
Host: example.com
Content-Length: 116
Transfer-Encoding: chunked
0
GET /admin/deleteUser?id=carlos HTTP/1.1
Host: example.com
Content-Length: 10
x=
The backend prepends GET /admin/deleteUser?id=carlos to the next legitimate user's request, causing it to execute with that user's session credentials.
Penetration testers use Burp Suite's HTTP Request Smuggler extension to automatically detect and exploit CL.TE and TE.CL variants, and to probe for HTTP/2 downgrade attacks (H2.CL, H2.TE).
Impact
- WAF and security control bypass — Security filters inspect the frontend's view of the request (benign) while the backend executes the smuggled malicious payload.
- Cross-user request hijacking — Subsequent users' requests are captured into the attacker's smuggled prefix, exposing session tokens, credentials, and request bodies.
- Cache poisoning — Smuggled responses are stored in shared caches and served to other users, enabling persistent XSS or credential theft at scale.
- Internal service access — Smuggled requests reach internal endpoints not accessible from the internet by exploiting the backend's trusted network position.
- Response splitting — HTTP response splitting via smuggling poisons CDN caches with attacker-controlled content.
Detection
- Use Burp Suite's HTTP Request Smuggler extension to automatically test for CL.TE, TE.CL, and HTTP/2 downgrade (H2.CL, H2.TE) variants against all in-scope hosts.
- Manually test by sending a request with both
Content-LengthandTransfer-Encoding: chunkedheaders and observing timeout or connection behavior differences between frontend and backend. - Use the differential timing technique: a CL.TE probe that sends an incomplete chunked body should cause the backend to timeout waiting for the terminating chunk—a longer response time indicates potential TE processing on the backend.
- Test for
Transfer-Encodingobfuscation bypass:Transfer-Encoding: xchunked,Transfer-Encoding:\tchunked, or duplicateTransfer-Encodingheaders that confuse some parsers. - Check for HTTP/2 support and test whether the server downgrades to HTTP/1.1 for backend communication.
Remediation
Normalize requests at the frontend. Configure the frontend proxy to canonicalize all requests before forwarding—resolve ambiguous Content-Length/Transfer-Encoding combinations and reject requests that contain both.
Use HTTP/2 end-to-end. Deploying HTTP/2 between frontend and backend eliminates CL/TE ambiguity since HTTP/2 uses binary framing with unambiguous message boundaries.
Disable backend connection reuse. Configure the backend to close connections after each request, preventing request buffer contamination. This has performance implications but eliminates the cross-request smuggling attack surface.
Reject ambiguous requests. Configure all components to reject requests containing both Content-Length and Transfer-Encoding headers, rather than applying precedence rules that can be exploited:
# Nginx — reject requests with both headers
if ($http_transfer_encoding ~* "chunked" ) {
return 400;
}
