
HTTP Request Smuggling (HRS) is a web security vulnerability that is often missed during security testing because it targets the way different servers process HTTP requests. It occurs when a front-end server and a back-end server interpret the same request differently, allowing an attacker to manipulate the request flow.
Depending on the setup, this can be used to bypass security controls, interfere with other users’ requests, access sensitive information, or affect application behavior. This guide explains how HTTP Request Smuggling works, how to identify it manually, and how the vulnerability can be exploited in real-world scenarios. It also covers common detection techniques and a practical case study to better understand the impact.
What is HTTP Request Smuggling?
HTTP Request Smuggling is a vulnerability that happens when different servers in a web application’s request chain interpret the same HTTP request in different ways.
Modern applications often have multiple components handling a request, such as:
- Front-end: Reverse proxy, load balancer, or WAF such as Nginx or AWS ALB
- Back-end: Application server such as Node.js, Java, Python, or similar technologies
The issue occurs when the front-end and back-end disagree about where an HTTP request starts or ends. An attacker can take advantage of this by specially crafting a request that:
- The front-end sees as a single HTTP request.
- The back-end interprets as multiple requests.
As a result, part of the attacker’s request can be treated as a separate request by the back-end. This “smuggled” request may then bypass controls implemented at the front-end and interact directly with the application.
The Core Vulnerability: HTTP Protocol Ambiguity
HTTP/1.1 provides two common ways for a server to determine where a request body ends:
- Content-Length (CL): Tells the server the exact size of the request body in bytes.
- Transfer-Encoding (TE): Allows the body to be sent in chunks, with a zero-length chunk marking the end.
The problem starts when different servers or components in the request chain handle these mechanisms differently. For example, a front-end proxy might use Content-Length while the back-end relies on Transfer-Encoding.
This difference can cause the two servers to disagree about where one request ends and another begins. An attacker can take advantage of this parsing difference to make part of a request appear as a separate request to the back-end, which is the basis of HTTP Request Smuggling.
The Three Main Types of HTTP Request Smuggling
HTTP Request Smuggling is commonly discussed in three forms: CL.TE, TE.CL, and TE.TE. The names describe how the front-end and back-end servers handle the request-length information.
1. CL.TE — Content-Length / Transfer-Encoding
In a CL.TE scenario, the front-end server determines the request length using Content-Length, while the back-end processes Transfer-Encoding: chunked.
A simplified example looks like this:
POST / HTTP/1.1
Host: vulnerable-app.com
Content-Length: 13
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: vulnerable-app.com
The front-end and back-end do not agree on where the request ends. The front-end follows the Content-Length value, while the back-end sees the 0 chunk and considers the chunked body finished. This difference can leave the following data to be interpreted as another HTTP request by the back-end.
The important point is not the exact payload, but the different interpretation of the request boundary.
2. TE.CL — Transfer-Encoding / Content-Length
With TE.CL, the behavior is reversed. The front-end uses Transfer-Encoding: chunked, while the back-end relies on Content-Length.
For example:
POST / HTTP/1.1
Host: vulnerable-app.com
Transfer-Encoding: chunked
Content-Length: 3
8c
POST /admin HTTP/1.1
Host: vulnerable-app.com
Content-Length: 144
admin_param=true
0
The front-end processes the body according to chunked encoding. However, if the back-end ignores or does not process the Transfer-Encoding header and instead follows Content-Length, it can interpret the same bytes differently.
This can cause part of the attacker’s data to remain in the connection and be interpreted as the beginning of another request.
3. TE.TE — Transfer-Encoding / Transfer-Encoding Obfuscation
In a TE.TE situation, both servers support Transfer-Encoding, but they handle the header differently.
An attacker may try to make the header look different to each component using variations such as duplicate headers or unusual formatting:
POST / HTTP/1.1
Host: vulnerable-app.com
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
8c[smuggled request]
0
For example, one server might ignore the unsupported xchunked value and process the second header, while another component may normalize or interpret the headers differently.
The result is the same fundamental problem:
Front-end interpretation
≠
Back-end interpretation
↓
Different request boundaries
↓
Possible request smuggling
The key difference
| Type | Front-end | Back-end |
|---|---|---|
| CL.TE | Content-Length | Transfer-Encoding |
| TE.CL | Transfer-Encoding | Content-Length |
| TE.TE | Transfer-Encoding | Different handling of Transfer-Encoding |
The names are useful for remembering the variants, but the real vulnerability is the parsing discrepancy between the servers. During testing, the goal is to identify whether that discrepancy actually exists rather than assuming that the presence of both headers automatically means the target is vulnerable.
Manual Detection Techniques
HTTP Request Smuggling can be difficult to identify because the front-end may return a normal response even when the back-end has parsed the request differently. Manual testing therefore focuses on finding differences in how the two servers handle request boundaries.
1. Timing-Based Detection
One useful technique is to send a request that makes the back-end wait for additional data. If the server waits longer than expected, the delay can indicate that the front-end and back-end are interpreting the request differently.
For example, a controlled test may use conflicting Content-Length and Transfer-Encoding headers:
POST / HTTP/1.1
Host: target.com
Content-Length: 13
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: target.com
The exact payload depends on the suspected parsing behavior. In a controlled test environment, an incomplete request can be used to see whether the back-end waits for bytes that the front-end has already considered part of a different request.
What to look for:
- A noticeable increase in response time
- A connection that remains open unexpectedly
- A timeout after sending an intentionally incomplete request
A delay alone does not prove request smuggling. Network latency, connection handling, rate limiting, and other server behavior can produce similar results, so the result should be reproduced and compared with a baseline.
2. Differential Response Analysis
Another approach is to compare how the target responds to requests containing conflicting message-length information.
For example, when investigating a possible CL.TE issue:
POST / HTTP/1.1
Host: target.com
Content-Length: 35
Transfer-Encoding: chunked
0
GET / HTTP/1.1
Host: target.com
The objective is to determine whether the front-end and back-end disagree about where the first request ends.
For a possible TE.CL issue, the direction is reversed:
POST / HTTP/1.1
Host: target.com
Transfer-Encoding: chunked
Content-Length: 3
8c
POST /api/test HTTP/1.1
Host: target.com
Content-Length: 10
admin=true
0
Possible indicators include:
- Different response status codes
- Unexpected delays
- Connection resets
- Requests appearing to be processed twice
- Responses that indicate that data was interpreted as another request
The important point is to compare the behavior against a normal request and repeat the test. A single unusual response is not enough to establish a vulnerability.
3. Observer Request Technique
An observer request can help confirm that a suspected smuggled request was actually processed.
The basic idea is:
Smuggled request
+
Observer request
↓
Back-end processes them in sequence
↓
Observable difference in the response
For example, during authorized testing, you might construct a request where the suspected smuggled request targets a harmless endpoint that produces a distinctive response.
The following request can then act as an observer:
POST / HTTP/1.1
Host: target.com
Content-Length: ...[smuggled request]
GET /known-test-endpoint HTTP/1.1 Host: target.com
If the server’s response changes in a way that is consistent with the smuggled request being processed first, this provides stronger evidence of request desynchronization.
Observer techniques are particularly useful because request smuggling is often difficult to confirm from the initial response alone.
4. Header Normalization Testing
Different HTTP components may normalize or reject unusual header syntax differently. Testing these differences can reveal potential parsing inconsistencies.
Examples worth investigating in an authorized environment include:
Different capitalization:
transfer-encoding: chunked
Transfer-encoding: chunked
TRANSFER-ENCODING: chunked
Duplicate headers:
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
Whitespace and malformed variations can also be relevant, although the exact behavior depends heavily on the HTTP implementation.
The testing process is:
- Establish a baseline using a normal request.
- Change one header variation at a time.
- Record status codes, response lengths, timing, and connection behavior.
- Compare the results across different request paths or server components.
- Repeat any suspicious result to rule out transient behavior.
A difference does not automatically mean the target is vulnerable. It indicates that the parsing behavior deserves further investigation.
5. Manual Connection Testing with Netcat
For low-level testing, a raw TCP client such as nc can be useful because it gives you direct control over the bytes sent to the server.
For example:
nc target.com 80
You can then manually enter an HTTP request:
POST / HTTP/1.1
Host: target.com
Content-Length: 35
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: target.com
The exact request should be adapted to the suspected CL.TE or TE.CL behavior and tested only against systems you are authorized to assess.
When testing manually, pay attention to:
- Whether the connection stays open
- Whether the server returns an unexpected status
- Whether a second request receives an unusual response
- Whether the connection is reset
- Whether behavior changes when requests are sent consecutively
Raw-socket testing is useful because tools such as browsers may automatically normalize headers or manage connections for you, making it harder to understand what the server actually received.
What to Look For
Across these techniques, the main indicators are consistent:
Normal request
↓
Expected response
Ambiguous request
↓
Unexpected delay / response / connection behavior
↓
Repeat test
↓
Consistent difference
↓
Investigate request desynchronization
The goal of manual detection is not simply to find a strange response. The goal is to demonstrate that two components are interpreting the same HTTP message differently and that this difference can cause the request stream to become desynchronized.
Real-World Incident: Netflix HTTP/2 Request Smuggling
Background
HTTP Request Smuggling is not limited to traditional HTTP/1.1 CL.TE or TE.CL attacks. Modern applications often accept HTTP/2 connections at the front end and then convert them to HTTP/1.1 when communicating with a back-end server. This conversion, known as HTTP/2 downgrading, can introduce its own request desynchronization problems.
A well-known example involved Netflix and was discovered during research into HTTP/2 request smuggling.
What Went Wrong?
Netflix’s infrastructure included a front-end component that accepted HTTP/2 requests and forwarded them to a back-end using HTTP/1.1.
HTTP/2 already has its own framing mechanism for determining the size of a request body. However, the Content-Length header can still be present. In the Netflix case, the front end did not properly validate the supplied Content-Length before converting the request to HTTP/1.1.
A simplified version of the problematic request looked like:
POST /n HTTP/2
:authority: www.netflix.com
content-length: 4
abcdGET /n HTTP/1.1
Host: example.com
Foo: bar
After the request was downgraded to HTTP/1.1, the back-end interpreted the first four bytes as the POST body:
abcd
Because the declared length was only four bytes, the remaining data:
GET /n HTTP/1.1
Host: example.com
Foo: bar
could be interpreted as the beginning of another HTTP request. This created a desynchronization between the front-end and back-end.
Why Was This Dangerous?
The desynchronization allowed an attacker to place a controlled prefix in front of a subsequent request sent through the affected connection. PortSwigger demonstrated that this could be used to manipulate responses and redirect JavaScript resources, potentially allowing attacks against active Netflix users, including the theft of sensitive information such as passwords and payment details.
The important lesson is that the attack did not depend on a traditional CL.TE or TE.CL conflict. The problem occurred during the HTTP/2 → HTTP/1.1 conversion.
Attacker
|
| HTTP/2 request
v
Front-end
|
| HTTP/2 → HTTP/1.1 downgrade
|
| Incorrect Content-Length handling
v
Back-end
|
| Different request boundary
v
Desynchronized connection
Root Cause
The underlying issue was associated with insufficient validation of Content-Length when HTTP/2 requests were converted into HTTP/1.1 requests.
The vulnerability was traced through Netflix’s Zuul proxy to the Netty HTTP/2 implementation and was tracked as CVE-2021-21295. Netty subsequently fixed the issue in version 4.1.60.Final.
Impact
The research demonstrated that the desynchronization could be used to:
- Add an attacker-controlled prefix to another request
- Manipulate responses returned to users
- Redirect JavaScript resources
- Potentially steal sensitive user information
- Affect other users sharing the vulnerable connection infrastructure
The actual impact depends on how the vulnerable front-end, proxy, and back-end components are deployed.
Key Takeaway
The Netflix case is a good example of why HTTP Request Smuggling should not be viewed only as a Content-Length versus Transfer-Encoding problem.
The bigger issue is inconsistent HTTP parsing between different components.
Even when HTTP/2 provides clear message framing, converting HTTP/2 requests into HTTP/1.1 can reintroduce request-boundary problems if headers such as Content-Length are not validated correctly.
For security testers, this means the following architecture deserves particular attention:
Client
|
| HTTP/2
v
Front-end / Proxy
|
| HTTP/1.1 downgrade
v
Back-end
Whenever HTTP versions are translated between components, the conversion boundary should be tested carefully for request desynchronization.
Detection Checklist for Security Teams
A structured testing process makes HTTP Request Smuggling easier to investigate and reduces the chance of causing unintended disruption.
Phase 1: Reconnaissance
- Identify the visible front-end components from headers, TLS information, and other passive indicators.
- Look for signs of reverse proxies, CDNs, WAFs, or load balancers.
- Collect server and framework information where it is safely exposed.
- Determine whether the application uses HTTP/1.1, HTTP/2, or a combination of protocols.
- Map the likely request path from the client through the front-end to the back-end.
Phase 2: Baseline Testing
Before sending unusual requests, establish how the application behaves normally.
- Send standard requests and record response times.
- Test requests over fresh and reused connections where possible.
- Record status codes, response lengths, connection behavior, and timeouts.
- Repeat tests to distinguish consistent behavior from normal network fluctuations.
A reliable baseline is important because timing alone is not enough to prove request smuggling.
Phase 3: Vulnerability Testing
Once the request path is understood, test for parsing inconsistencies in a controlled environment.
- Investigate possible CL.TE behavior.
- Investigate possible TE.CL behavior.
- Test how duplicate or unusual
Transfer-Encodingheaders are handled. - If HTTP/2 is supported, investigate possible HTTP/2 downgrade or request-framing issues.
- Monitor for unexpected delays, connection hangs, response changes, or evidence that requests are being processed out of sequence.
Use harmless endpoints and non-destructive payloads whenever possible.
Phase 4: Confirmation
A suspicious response should be reproduced before reporting the issue.
- Demonstrate that the front-end and back-end interpret the same request differently.
- Confirm that the suspected second request is actually processed.
- Use an innocuous endpoint or controlled marker where possible.
- Record the exact request, response, connection behavior, and relevant server configuration.
- Avoid testing techniques that could affect other users unless they are explicitly authorized.
Phase 5: Reporting
A good request-smuggling report should include:
- A concise description of the parsing discrepancy.
- The affected components and protocols.
- A safe proof of concept.
- Evidence showing the different request boundaries.
- The potential impact based on the application’s architecture.
- Relevant server and software versions, where confirmed.
- Recommended remediation and validation steps.
Avoid claiming impacts such as authentication bypass or data theft unless the testing actually demonstrates them.
Defensive Recommendations
For Developers and DevOps
1. Reject ambiguous requests
Front-end and back-end components should follow the same request-parsing rules. Requests containing conflicting or invalid message-length information should generally be rejected rather than interpreted differently by different components.
For example, organizations should carefully validate requests containing both:
Content-Length: ...
Transfer-Encoding: chunked
The exact handling should follow the HTTP implementation and deployment architecture rather than relying on ad-hoc application code.
2. Keep HTTP parsing consistent
The safest architecture is one where every component in the request path uses compatible parsing rules.
Review:
Client
↓
CDN
↓
WAF
↓
Load Balancer
↓
Reverse Proxy
↓
Application Server
Each transition should be checked for differences in HTTP parsing and protocol conversion.
3. Treat HTTP/2 carefully
HTTP/2 uses binary framing, which removes many of the request-boundary ambiguities found in HTTP/1.1. However, HTTP/2 does not automatically prevent request smuggling.
Problems can still appear when HTTP/2 requests are downgraded to HTTP/1.1:
HTTP/2
↓
Proxy / Gateway
↓
HTTP/1.1
↓
Back-end
If your infrastructure performs this conversion, validate headers such as Content-Length carefully and test the downgrade path specifically.
4. Validate message lengths
Servers and proxies should reject malformed or contradictory message-length information instead of trying to guess the sender’s intention.
Pay particular attention to:
- Invalid
Content-Lengthvalues - Conflicting
Content-Lengthheaders - Conflicts between
Content-LengthandTransfer-Encoding
5. Keep infrastructure components updated
Request parsing bugs can exist in proxies, frameworks, HTTP libraries, and application servers. Keep these components patched and review security advisories for the specific technologies used in the request path.
6. Monitor for suspicious connection behavior
Useful signals can include:
- Unusual request timeouts
- Repeated malformed HTTP requests
- Unexpected
Transfer-Encodingcombinations - Multiple requests appearing on a connection in an unusual sequence
- Abnormal connection resets or response delays
Monitoring should support detection, but it should not be treated as a replacement for secure request parsing.
Tools for Manual Detection
| Tool | Purpose | Typical Use |
|---|---|---|
| Burp Suite Professional | HTTP testing and request analysis | Repeater, Inspector, and request-smuggling research |
| curl | Direct HTTP testing | Send controlled requests and inspect responses |
netcat (nc) | Raw TCP communication | Manually control HTTP request boundaries |
| Wireshark | Network traffic analysis | Inspect connections and transmitted data |
| Python | Custom testing | Build controlled request-parsing test cases |
For manual testing, Burp Suite is particularly useful because it lets you inspect and modify requests at a low level while keeping the testing workflow manageable.
Conclusion
HTTP Request Smuggling is fundamentally a problem of inconsistent HTTP parsing. The vulnerability appears when different components in the same request chain disagree about where one request ends and another begins.
The most important concepts to take away are:
- Understand the protocol —
Content-Length,Transfer-Encoding, HTTP/1.1 framing, and HTTP/2 behavior are central to the vulnerability. - Understand the architecture — identify how requests travel through CDNs, WAFs, proxies, load balancers, and application servers.
- Look for parsing differences — the important question is not simply whether conflicting headers exist, but whether different components interpret them differently.
- Confirm carefully — timing anomalies and unusual responses are useful clues, but reproducible evidence of request desynchronization provides stronger confirmation.
- Consider protocol conversion — HTTP/2 can remove some HTTP/1.1 ambiguity, but HTTP/2-to-HTTP/1.1 downgrades can introduce their own request-smuggling risks.
For security teams, the goal should be to make every component in the request path agree on how HTTP messages are parsed and framed. Consistent parsing, strict validation, secure configuration, and regular testing can significantly reduce the risk of request-smuggling vulnerabilities.
References & Further Reading
- PortSwigger Web Security Academy — HTTP Request Smuggling
- James Kettle — Request Smuggling Desync Attacks, Black Hat 2019
- CWE-444 — Inconsistent Interpretation of HTTP Requests
- RFC 7230 — HTTP/1.1 Message Syntax and Routing
- RFC 9113 — HTTP/2
Also Read
Continue exploring our security research on common web and application vulnerabilities:
- OAuth 2.0 Attacks: From Misconfiguration to Account Takeover — how one weak assumption in a login flow leads to full account takeover.
- Why Insecure Direct Object References Are Still Widely Found Today — the access-control flaw that keeps slipping past reviews and scanners.
- Pentesting Electron-Based Desktop Applications: A Practical Guide — when a small web bug in a desktop app escalates to full system compromise.