HTTP Attacks
Introduction to Request Smuggling
HTTP Request Smuggling or sometimes also called Desync Attacks is an advanced attack vector that exploits a discrepancy between a frontend and a backend system in the parsing of incoming HTTP requests. The frontend system can be any intermediary system such as a reverse proxy, web cache, or web application firewall (WAF), while the backend system is typically the web server. Since request smuggling is an advanced technique, it requires a solid understanding of TCP and HTTP to understand how it works. In the upcoming sections, we will generally refer to the frontend system as the reverse proxy and the backend system as the web server. However, as stated above, the actual functionality of the frontend and backend systems does not matter for this vulnerability.
We will discuss the basics in this section, so make sure you understand them well before moving on. If you feel overwhelmed at any point you may want to go back and repeat topics from earlier modules to strengthen your foundations in TCP and HTTP.
TCP Stream of HTTP requests
The Transmission Control Protocol (TCP) is a transport layer protocol that provides reliable and ordered communication. In particular, TCP is a stream-oriented protocol, meaning it transmits streams of data. The application layer protocol (which can be HTTP for instance) does not know how many TCP packets were transmitted, it just receives the raw data from TCP.
HTTP requests and responses are transmitted using TCP. In HTTP/1.0, each HTTP request was sent over a separate TCP socket. However, since HTTP/1.1, requests are typically not transmitted over separate TCP connections but the same TCP connection is used to transmit multiple request-response pairs. This allows for better performance since the establishment of TCP connections takes time. If a new HTTP request required a new TCP connection, the overhead would be much higher. In particular, in settings where a reverse proxy sits in front of the actual web server and all requests are transmitted from the reverse proxy to the web server, the TCP socket is usually kept open and re-used for all requests:

Since TCP is stream-oriented, multiple HTTP requests are sent subsequently in the same TCP stream. The TCP stream contains all HTTP requests back-to-back as there is no separator between the requests. Consider the following simplified representation of a TCP stream containing two HTTP requests: a POST request in red and a GET request in green:
POST / HTTP/1.1
Host: clte.htb
Content-Length: 5
HELLOGET / HTTP/1.1
Host: clte.htb
The POST request contains a request body consisting of the word HELLO. The subsequent GET request starts immediately after the POST request's body ends, there is no delimiter. Thus, to parse the HTTP requests correctly, both the reverse proxy and web server need to know where the current request ends and where the next request starts. In other words, both systems need to know where the request boundaries are within the TCP stream.
Content-Length vs Transfer-Encoding
To figure out the length of the current request's body, we can use HTTP headers. In particular, the Content-Length (CL) and Transfer-Encoding (TE) headers are used to determine how long an HTTP request's body is. Let's have a look at how both of these headers specify the request length.
Content-Length
The CL header is most commonly used and you have probably seen it before. It simply specifies the byte length of the message body in the Content-Length HTTP header. Let's look at an example request:
POST / HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
param1=HelloWorld¶m2=Test
The CL header specifies a length of 29 bytes. Therefore, all systems know that this HTTP request contains a request body that is exactly 29 bytes long.
Transfer-Encoding
On the other hand, the TE header can be used to specify a chunked encoding, indicating that the request contains multiple chunks of data. Let's look at the same request with chunked encoding:
POST / HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
1d
param1=HelloWorld¶m2=Test
0
We can see that the HTTP header Transfer-Encoding specifies a chunked encoding. The body now consists of chunks of data. Each chunk is preceded by the chunk size in hex on a separate line, followed by the payload of the chunk. The request is terminated by a chunk of size 0. As we can see, the request contains a chunk of size 0x1d which is equal to 29 in decimal followed by the same payload as the previous request. Afterward, the request is terminated by the empty chunk.
Note that the chunks sizes and chunks are separated by the CRLF control sequence. If we display the CRLF characters, the request body looks like this:
1d\r\nparam1=HelloWorld¶m2=Test\r\n0\r\n\r\n
Lastly, we need to discuss how a request should be treated that contains both a CL and a TE header. Luckily for us, the HTTP/1.1 standard defines the behavior in the RFC here:
If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
So, if a request contains both a CL and TE header, the TE header has precedence and the CL header should be ignored.
Desynchronization
Request smuggling attacks exploit discrepancies between the reverse proxy and web server. In particular, the attack forces a disagreement in the request boundaries between the two systems, thus causing a desynchronization which is why request smuggling attacks are sometimes also called Desync Attacks. This can be achieved by exploiting bugs in the web server or reverse proxy software, lack of support for chunked encoding, or incorrect parsing of any of the CL or TE headers as we will see in the upcoming sections.
For now, let's discuss what desynchronization achieves. Generally, HTTP requests are viewed in isolation, meaning different HTTP requests cannot influence each other. This is an important trait of HTTP traffic since a lot of users typically access the same web server. It could have potentially catastrophic consequences if an attacker can influence other users' requests with his own request. Since multiple requests are sent over the same TCP stream as discussed above, a disagreement in request boundaries by different systems enables an attacker to achieve exactly that. When the reverse proxy and web server disagree on the boundaries of an HTTP request, there is a discrepancy at the beginning of the subsequent request. This leads to data being left in the TCP stream that one of the two systems treats as a partial HTTP request, while the other system treats it as part of the previous request. When the next request arrives, the behavior of the reverse proxy and web server thus differs, leading to potentially serious security issues. By sending a specifically crafted request that forces such a disagreement, an attacker would thus be able to manipulate the subsequent request which may come from an entirely different user:

Depending on the specific type of disagreement between the systems, HTTP request smuggling vulnerabilities can have a different impact, including mass exploitation of XSS, stealing of other users' data, and WAF bypasses. For more details on HTTP request smuggling attacks, have a look at this great blog post by James Kettle.
Table of Contents
Introduction to HTTP Attacks
Introduction to HTTP AttacksCRLF Injection
Introduction to CRLF Injection Log Injection HTTP Response Splitting SMTP Header Injection CRLF Injection Prevention & ToolsHTTP Request Smuggling/Desync Attacks
Introduction to Request Smuggling CL.TE TE.TE TE.CL Vulnerable Software Exploitation of Request Smuggling Request Smuggling Tools & PreventionHTTP/2 Downgrading
Introduction to HTTP/2 HTTP/2 Downgrading Further H2 Vulnerabilities HTTP/2 Downgrading Tools & PreventionHTTP Attacks - Skills Assessment
Skills AssessmentMy Workstation
OFFLINE
/ 1 spawns left