Hello! Welcome back to our advanced penetration testing course.
In the last lesson, we focused on attacking the application's authentication logic by exploiting vulnerabilities within JSON Web Tokens. You learned how to forge tokens by stripping signatures, cracking weak secrets, and confusing algorithms.
Today, we shift our focus from the application logic itself to the underlying infrastructure that delivers it. We will be covering a powerful and often subtle vulnerability class that arises from ambiguities in the HTTP protocol. Our goal for this lesson is to learn how to identify and exploit HTTP Request Smuggling vulnerabilities to bypass security controls and access internal systems.
This attack targets the desynchronization between front-end servers (like reverse proxies and load balancers) and back-end application servers, allowing an attacker to "smuggle" malicious requests past security filters.
1. The Architecture of a Modern Web Application
To understand request smuggling, you first need to understand how most modern web traffic is handled. A typical setup involves a chain of servers:
- Front-end Server: A reverse proxy, load balancer, or CDN that receives requests directly from users. Its job is to route traffic, handle TLS termination, cache content, and enforce security rules.
- Back-end Server: The application server that runs the actual business logic (e.g., a Python Flask app, a Node.js server).
Critically, for efficiency, the front-end server often maintains a persistent, reused TCP connection to the back-end. This means multiple HTTP requests from different users can be sent back-to-back over the same connection. It is this reuse that creates the conditions for request smuggling.
HTTP Request Smuggling Explained (with James Kettle)
Let's start with a foundational explanation from NahamSec and James Kettle, the researcher who revitalized this field. This clip explains why understanding HTTP pipelining is key and how the vulnerability lives in the gap between the front-end and back-end servers.
Watch from 05:04 to 09:16. Focus on: The concept of HTTP requests as a continuous stream over a single TCP connection. The core problem: The front-end and back-end disagree on where one request ends and the next begins. The two key headers involved: Content-Length and Transfer-Encoding.
As the video explains, the HTTP specification provides two ways to specify the length of a request body:
Content-Length(CL): A header that explicitly states the size of the body in bytes.Transfer-Encoding: chunked(TE): A header that indicates the body will be sent in a series of chunks. Each chunk is prefixed with its size in hexadecimal, and the entire body is terminated by a chunk of size0.
According to the specification (RFC 2616), if a request has both Content-Length and Transfer-Encoding headers, the Content-Length header should be ignored. However, not all servers follow this rule perfectly, leading to a "desync".

2. The Classic Desync Attacks: CL.TE and TE.CL
There are two primary forms of classic HTTP/1.1 request smuggling, named for the header prioritized by the front-end and back-end servers, respectively.
The ultimate Bug Bounty guide to HTTP request smuggling
This guide from YesWeHack provides clear, concise definitions and examples for the two main types of request smuggling attacks. We'll use it to define CL.TE and TE.CL.
Read the sections titled 'CL.TE (Content-Length/Transfer-Encoding) vulnerabilities' and 'TE.CL (Transfer-Encoding/Content-Length) vulnerabilities'. Focus on understanding how the differing header interpretations lead to part of the request body being left behind on the socket.
CL.TE Desync
- The front-end server uses the
Content-Lengthheader. - The back-end server uses the
Transfer-Encoding: chunkedheader.
Attack Mechanism:
- The attacker sends a POST request containing both
Content-LengthandTransfer-Encoding: chunkedheaders. - The
Content-Lengthis set to be shorter than the full request, only covering up to the0that signifies the end of a chunked request. - The front-end reads the
Content-Lengthheader, forwards that many bytes to the back-end, and believes the request is complete. - The back-end reads the
Transfer-Encodingheader. It sees the0and believes the request has finished. - The remaining data sent by the attacker (the "smuggled" request) is left on the TCP socket, waiting to be prepended to the next incoming request from a victim.
Here is a CL.TE attack smuggling a request to /admin:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 64
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: vulnerable-website.com
Foo: bar
The front-end sends all 64 bytes. The back-end processes the chunked request, ending after 0\r\n\r\n, and leaves the GET /admin... part on the socket.
TE.CL Desync
- The front-end server uses the
Transfer-Encoding: chunkedheader. - The back-end server uses the
Content-Lengthheader.
Attack Mechanism:
This is the reverse scenario. The attacker crafts a chunked request where the final chunk is the smuggled request. A Content-Length header is set to only cover the first part of the request. The front-end processes the full chunked request, but the back-end stops reading after the number of bytes specified in Content-Length, leaving the smuggled request on the socket.
3. Practical Detection and Exploitation
Detecting these vulnerabilities often involves sending carefully crafted requests and observing the server's response time. If a server is waiting for data that never arrives (because of a desync), it will eventually time out. This timing difference can be used as an oracle to confirm the vulnerability.
The real power, however, comes from exploiting it.
HTTP Request Smuggling Explained (with James Kettle)
Now, let's watch a full, hands-on demonstration. In this video, James Kettle walks through a PortSwigger Academy lab, showing how to first detect a CL.TE vulnerability and then exploit it to turn a self-XSS into a stored XSS that affects other users.
Watch the extended demonstration from 11:07 to 20:26. This is the core practical part of the lesson. Pay close attention to: The methodical process of testing for CL.TE vs. TE.CL using Burp Repeater. How a timing delay confirms the CL.TE vulnerability. The construction of the smuggled request to target a different endpoint. The trick of adding a partial header (x-ignore: x) to 'absorb' the victim's request headers and avoid errors. The final payload that smuggles a POST request to deliver an XSS payload.
Test your understanding!
In the video walkthrough, why was it necessary to add the x-ignore: x header at the end of the smuggled GET request? What problem did this solve?
Show answer
When the smuggled request (GET /notfound ...) was prepended to the victim's request (GET / ...), the back-end server received a malformed stream of data like GET /notfound ... GET / .... This confused the server, resulting in a 400 Bad Request error.
By adding a partial header like x-ignore: x without a final CRLF, the victim's entire request line (GET /...) was appended as the value of the x-ignore header. The back-end server saw a single valid request: GET /notfound with a very long, meaningless header (x-ignore: xGET /...). This allowed the smuggled request to be processed cleanly while the victim's request was effectively neutralized.
4. Advanced Exploitation and Impact
Request smuggling is a high-severity vulnerability because it can be used to achieve a wide range of malicious goals. The video you just watched demonstrated chaining it with XSS, but the impact can be far more direct.
Practical Attacks Using HTTP Request Smuggling by @defparam #NahamCon2020
Let's explore some real-world attack scenarios presented by security researcher @defparam. This talk showcases practical techniques used in actual bug bounty reports to achieve critical impact.
This video contains several 'recon stories'. Watch the following segments: Bypassing ACLs to Access Admin Panels (11:14 - 15:23): This is a classic exploitation path. An attacker finds a restricted endpoint in robots.txt and uses a TE.CL desync to smuggle a request directly to the back-end, bypassing the front-end block. Achieving Account Takeover (15:23 - 19:51): This example shows how a CL.TE desync on an API server was used to add the attacker's user ID as an owner to a victim's account. Response Queue Poisoning (33:52 - 42:44): This is an extremely dangerous variant. Instead of just desynchronizing the requests, the attacker splits a request in such a way that it causes the back-end to generate an extra response. This desynchronizes the response queue, causing victims to receive responses meant for other users—including session tokens and PII. This is a critical finding.
The key takeaway is that the smuggled request is processed by the back-end with the same level of trust as if it came from the front-end proxy. This allows you to bypass IP-based access controls, authentication checks, and other security measures enforced at the edge.
5. HTTP/2 and Modern Variants
You might think that HTTP/2, with its more rigid, binary framing structure, would eliminate this vulnerability. While true for end-to-end HTTP/2 communication, many real-world systems perform HTTP/2 downgrading, where the front-end speaks HTTP/2 to the client but downgrades the request to HTTP/1.1 to communicate with the back-end. This process can reintroduce the same classic ambiguities.
Advanced request smuggling | Web Security Academy
PortSwigger's research outlines how these new protocol interactions create novel attack vectors. Let's briefly review the core concepts.
Read the following sections from the PortSwigger article: HTTP/2 request smuggling: Focus on the concept of HTTP/2 downgrading. H2.CL vulnerabilities: Understand how injecting a content-length header in an HTTP/2 request can be abused during the downgrade. Request smuggling via CRLF injection: This is a powerful technique unique to HTTP/2 downgrading. Because HTTP/2 header values can contain characters like \r\n, an attacker can inject them into a header value to create a new header when the request is downgraded to plain-text HTTP/1.1.
These advanced techniques show that request smuggling continues to evolve with web protocols. As a tester, you need to be aware that even modern stacks can be vulnerable if they are not configured correctly.
Conclusion
HTTP Request Smuggling is a complex but powerful vulnerability. It requires a deep understanding of the HTTP protocol and the architecture of your target. Today, you have learned the fundamental theory and seen practical, high-impact exploitation techniques.
Key Takeaways:
- The Root Cause: A desynchronization between front-end and back-end servers due to ambiguous
Content-LengthandTransfer-Encodingheaders. - The Main Variants: CL.TE (front-end trusts CL, back-end trusts TE) and TE.CL (front-end trusts TE, back-end trusts CL).
- Detection: Often relies on observing timing differences when sending ambiguous requests. Tools like Burp's HTTP Request Smuggler can automate this.
- Impact: Is severe and varied, ranging from bypassing access controls and accessing internal admin panels to chaining with other vulnerabilities like XSS, and in the most critical cases, poisoning the response queue to steal user sessions and data.
- Modern Stacks: Even systems using HTTP/2 can be vulnerable if they perform HTTP/2-to-HTTP/1.1 downgrading.
Next Lesson Preview:
One of the most devastating consequences of request smuggling is Web Cache Poisoning, where you cause a malicious response to be saved in a web cache and served to countless users. In our next lesson, we will dive deep into this attack class, exploring how it can be triggered not only by request smuggling but also by exploiting unkeyed inputs in HTTP requests.