0x00 Request Smuggling for Bug Bounty
HTTP request smuggling is a web security vulnerability that arises when an intermediary server (like a proxy or load balancer) interprets HTTP requests differently than the backend. This discrepancy allows an attacker to "smuggle" malicious requests into the backend server's processing queue, potentially leading to various security issues.
The Core Problem: Discrepancies in Request Parsing
The vulnerability stems from inconsistencies in how the frontend and backend servers determine the boundaries of HTTP requests. HTTP/1.1 uses two primary methods for defining request length:
Content-Length: Specifies the exact length of the request body in bytes.
Transfer-Encoding: chunked: Uses chunked encoding, where the body is sent in chunks, each prefixed with its size.
When both headers are present, RFC 7230 states that Transfer-Encoding
should be preferred. However, if the frontend and backend servers disagree on which header to prioritize, or if they handle chunked encoding differently, request smuggling becomes possible.
0x01 Types of HTTP Request Smuggling
There are three main types of HTTP request smuggling, categorized by how the frontend and backend servers handle Content-Length
and Transfer-Encoding
headers:
CL.TE (Content-Length, Transfer-Encoding): The frontend server uses the
Content-Length
header, while the backend server uses theTransfer-Encoding
header.TE.CL (Transfer-Encoding, Content-Length): The frontend server uses the
Transfer-Encoding
header, while the backend server uses theContent-Length
header.TE.TE (Transfer-Encoding, Transfer-Encoding): Both the frontend and backend servers use the
Transfer-Encoding
header, but they handle it differently, leading to inconsistencies.
0x02 CL.TE Smuggling: A Detailed Example
Attacker's Malicious Request:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 63
Transfer-Encoding: chunked
0
POST /hidden-resource HTTP/1.1
Host: vulnerable-website.com
Content-Length: 10
malicious
Explanation:
The attacker sends a request with both
Content-Length
andTransfer-Encoding
headers.The frontend server prioritizes
Content-Length: 63
. It processes the first 63 bytes as a single request.The backend server prioritizes
Transfer-Encoding: chunked
. It processes the request in chunks.The "0\r\n\r\n" sequence indicates the end of the chunked encoding to the backend.
The remaining part of the attacker's request, starting from "POST /hidden-resource...", is treated as the beginning of the next request by the backend server.
Consequences:
The next legitimate request from another user will be appended to the smuggled request. For example, if another user sends the following request:
GET /index.html HTTP/1.1
Host: vulnerable-website.com
... (other headers)
The backend server will see this as:
POST /hidden-resource HTTP/1.1
Host: vulnerable-website.com
Content-Length: 10
maliciousGET /index.html HTTP/1.1
Host: vulnerable-website.com
... (other headers)
This means the backend server will process the smuggled request (POST /hidden-resource
) and then treat the beginning of the legitimate user's request (GET /index.html
) as part of the smuggled request's body. This can lead to:
Access to restricted resources: The attacker can access resources they shouldn't be able to, like
/hidden-resource
.Session hijacking: The attacker can potentially steal session cookies from other users.
Cache poisoning: The attacker can poison the cache with malicious content.
Denial of service: The attacker can disrupt the service for other users.
0x03 Example: CL.CL - The Safe Case
Not every configuration is vulnerable. When both ends trust CL, the system is aligned.
The Request
POST / HTTP/1.1
Host: toxsec.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
q=vulnerable
What Happens
Edge and origin: Both read 12 bytes and finish cleanly.
No leftover: Connection is ready for the next request.
Signal to Watch
Deliberately misstate CL (±1). You should get consistent 400s from both ends — a clean failure, not a desync.
0x04 HTTP Request Smuggling Recon
Recon doesn’t need to be destructive. Start with harmless probes to see how edge and origin interpret length.
Send harmless duplicates. Same request twice: once with CL, once with TE. Both logically valid.
Toggle both headers. Put CL and TE together and see which one “wins.”
Observe subtle signals:
408 Request Timeout — origin waiting for bytes the edge considered done.
502 Bad Gateway — edge killed a desynced connection.
Second GET stall — pipelined follow-up GET hangs.
These discrepancies map which family a target falls into. Once you know the camp, you can plan payloads, cache poisons, and header smuggles with purpose.
Duplicate Headers
GET /ping HTTP/1.1
Host: toxsec.com
X-Foo: A
X-Foo: B
Some servers collapse duplicates, others preserve them, and intermediaries may rewrite them entirely. That difference fingerprints the chain.
Whitespace Quirks
POST /ping HTTP/1.1
Host: toxsec.com
Transfer-Encoding : chunked
0
vs
POST /ping HTTP/1.1
Host: toxsec.com
Transfer-Encoding:chunked
0
If one parser tolerates the extra space and the other doesn’t, error codes diverge.
Pipelined GETs
GET /ping HTTP/1.1
Host: toxsec.com
GET /status HTTP/1.1
Host: toxsec.com
If both return cleanly, the chain is consistent.
If the second request stalls or mutates, you likely desynced the queue.
0x05 Bug Reporting & Impact Framing
Request smuggling is one of those bugs where the report is half the exploit. A raw CL/TE mismatch looks abstract; frame it as cache poisoning or credential hijack, and the risk becomes obvious.
Structure the Report
Summary: One-line impact statement.
“HTTP request smuggling enables cache poisoning and session hijack.”
Technical details: Vulnerable endpoint, headers used, observed signals (timeouts, stalls, error codes).
Attack chain: How desync becomes business risk (e.g., poisoned cache serves attacker content).
PoC: Minimal crafted request that reproduces.
Emphasize Impact
Cache poisoning: Inject into shared CDN cache → many users affected.
Session hijack: Victim’s request inherits attacker-controlled prefix → credential leakage.
WAF bypass: Edge blocks payload, origin receives it via desync.
Admin action forgery: Smuggle a privileged request in front of a victim’s.
Keep It Professional
No live poisoning in production. Use controlled demos or labs.
Screenshots, timing charts, and cache behavior tell the story.
If triage calls it “theoretical,” walk them through the spliced queue from probe to impact.
0x06 Debrief - CL.TE Request Smuggling
Message delimiting
Content-Length (CL): “Read exactly N bytes.”
Transfer-Encoding: chunked (TE): “Read chunks until a
0
marker says stop.”Trouble starts when both headers appear together, or when one is malformed. If the edge trusts CL and the origin trusts TE, their views drift.
Header normalization
Duplicates: Some servers use the first instance, some the last, some merge them.
Formatting quirks: Case changes, extra spaces, or stray tabs can alter behavior.
Legacy folding: Old parsing rules still cause issues with folded headers or comma-joined values.
Protocol bridges
HTTP/2 → HTTP/1 downgrade: Front-end servers often translate H2 frames into H1 requests. If the translation isn’t strict, mismatches creep in.
:authority
vs.Host
: Proxies may generate one while origins trust the other.
Learn the families, read the signals, and frame the report in business terms. If you’d like to see tips for effective bug bounty reporting, along with a real example of a HackerOne bug report, take a look at this ToxSec article here.