Request Smuggling - Description and Procedure for Testing

Request Smuggling

Description and Procedure for Testing

Andrea Hauser
by Andrea Hauser
on March 24, 2022
time to read: 13 minutes

Keypoints

This is how Request Smuggling works

  • Request smuggling occurs when, in a chain of servers, the servers disagree on where the request body ends
  • there are two ways to specify the request body, content-length and transfer-encoding: chunked
  • effects of request smuggling can be reading sensitive data from other users or exploiting otherwise theoretically exploitable vulnerabilities
  • when testing for these vulnerabilities, testers need to be careful, as one wrong request can potentially affect all users of the web application

Request smuggling is a vulnerability that occurs when several servers are involved in processing a request and these servers disagree on where the body of the request begins and ends. Examples of such chains of servers are reverse proxies with their back-end or the widely used load balancing, in which a front-end receives requests and sends them to different back-end servers for processing depending on the load. The impact of a successful request smuggling attack can be devastating, sensitive information can be tapped, otherwise unreachable vulnerabilities can be exploited, and the normal use of the website for all users can be affected.

Normally, with HTTP/1.1 between the front-end server and the back-end server, the connection is not terminated after each request and a new connection is established. This is done to save resources, because each new connection takes time. This means that the only thing in the queue between the front-end and the back-end that splits the requests from each other are the sizes specified in a request.

Requests from two different users are sent from the front-end to the back-end over the same connection

Content-Length and Transfer-Encoding Header

There are two different ways to specify the size of the body in an HTTP/1.1 request. This can be done on the one hand via the Content-Length header and on the other hand via the Transfer-Encoding header. The Content-Length header specifies the size of the body in bytes. The Transfer-Encoding header with the parameter chunked works in so-called chunks. Example of such a request:

POST /test HTTP/1.1
Host: example.com
Transfer encoding: chunked

6 test=1 0

The size of the chunk in bytes in hexadecimal is specified first in the body. In the case of the example the body test=1 is 6 bytes large. In principle, a body can contain several such chunks with their respective size specification. A chunked request is terminated with a 0 and two line breaks.

Main Vulnerability Types Request Smuggling

A request smuggling attack can now be executed by getting the servers in the chain to process different size specifications. Servers are given multiple ways to identify size information by specifying both Content-Length and Transfer-Encoding headers. There are three different ways servers can be vulnerable to the vulnerability.

Shows what happens when an attacker sends a spoofed request and the front-end server and the back-end server disagree on the size of the body

However, before going into specific attack possibilities, here is a word of warning: testing these vulnerabilities may impact third parties who are using the tested website at the same time. Testing for this vulnerability should only be done against production environments after the tester has already studied the vulnerability in detail and is aware of the impact of request smuggling. To get a feel for the vulnerability, Portswigger’s Labs from the Web Security Academy are recommended. Reading into this topic is advised, as request smuggling can have far-reaching consequences. In the example of Slack, taking over the session cookie of arbitrary users and thus reading arbitrary messages would be possible. The full description of this vulnerability can be found in HackerOne Report 737140.

The definitions of vulnerability types that follow now follow the notation below:

{used size specification front-end}.{used size specification back-end}

Vulnerability Type CL.TE

In the case of CL.TE, the front-end uses the Content-Length of the request to size the body and ignores the Transfer-Encoding header. However, the back-end takes the Transfer-Encoding header as a starting point to calculate the size of the body. In an example, this would look like this.

POST /test HTTP/1.1
Host: example.com
Content-Length: 13
Transfer encoding: chunked

0
--> back-end reads up to here because of the 0 chunk
Injected --> front-end reads up to here

In this example the --> indicate comments and can be ignored for the size calculations of the body. The content length of 13 bytes comes about because in addition to the letters visible in the example, the invisible characters \r and \n are used for the two line breaks.

Since the back-end finishes processing the request earlier than what the front-end sent, the rest of the requests remain in the pipeline between the front-end and the back-end. As soon as a next request arrives, the remainder of the previous request still in the pipeline is added before this new request. So a new request would look like this in the back-end:

InjectedGET /test HTTP/1.1
Host: example.com

Vulnerability Type TE.CL

In the case of TE.CL, the front-end uses the Transfer-Encoding header and the back-end uses the Content-Length header. In an example, this looks like this.

POST /test HTTP/1.1
Host: example.com
Content-Length: 8
Transfer-Encoding: chunked

D
test=Injected --> back-end reads up to and with test=
0
--> front-end reads up to here

Since the back-end finishes processing the request earlier than what the front-end sent, the rest of the request remains in the pipeline between the front-end and the back-end. As soon as a next request arrives, the remainder of the previous request still in the pipeline is added before this new request. So, a new request would look like this in the back-end:

Injected
0

GET /test HTTP/1.1
Host: example.com

Vulnerability Type TE.TE

In the case of TE.TE, both the front-end and the back-end use the Transfer-Encoding header. However, by manipulating the Transfer-Encoding header, one of the systems can be made to stop recognizing the header and fall back to the Content-Length, while the other server still uses the Transfer-Encoding header. Depending on which system no longer uses the Transfer-Encoding header, the CL.TE or TE.CL vulnerability type is used.

There are numerable variations on how the Transfer-Encoding header can be obfuscated. For example, it has been found that certain servers only look for the string chu in the Transfer-Encoding header to determine if it is a chunked request. Coupled with a system that does not handle it this way, the Transfer-Encoding: chu header leads to a mismatch between the two servers and opens up the possibility for request smuggling attacks. Other examples of obfuscating the Transfer-Encoding header are:

An example of how a transfer encoding header obfuscation technique could be used to perform a request smuggling attack on a U.S. Department of Defense website can be found in HackerOne Report 526880.

Continuing Attacks

The three types of vulnerabilities shown above are the main types of request smuggling attacks on which other attacks are based. For example, a request smuggling vulnerability makes it possible to exploit other vulnerabilities that would otherwise be impossible to exploit or have limited impact. Examples of this are attacks that take place in headers that cannot normally be controlled by an attacker or XSS vulnerabilities that actually only affect an area that an attacker does not normally have access to. In HackerOne Report 955170 it is explained how a normally harmless behavior in a redirect in the case of a request smuggling vulnerability leads to an open redirect and in this case then led to the execution of JavaScript controlled by the researcher.

If in a request smuggling attack not only a part of a request is added to the pipeline as shown so far, but a second complete, valid request is added, it is even possible to desynchronize the entire communication. Because then the front-end thinks it has forwarded one request, but the back-end sees two requests and will send two responses accordingly, so now each user will not receive the response to his requests, but the response of the previous user. This is of course a very destructive approach, since all users of this front-end back-end connection are affected.

With the introduction of the HTTP/2 protocol, there are more attack surfaces during protocol downgrades between the front-end and the back-end server if the request is not converted cleanly during the downgrade. However, this will be discussed in more detail in a separate article on HTTP/2 at a later date.

Notes for Testers

Due to the far-reaching possibilities of this vulnerability, testing can lead to effects on the entire environment in the event of a bug; testing should be approached with care accordingly. With a current version of BurpSuite Pro, a check is already made for request smuggling when an Active Scan is performed. A procedure is chosen in which the impact on other users is kept as small as possible. The easiest way to do this is to work with consciously triggered time-outs. For example, if a CL.TE vulnerability is present, a time-out can be triggered with the following request:

POST /test HTTP/1.1
Host: example.com
Content-Length: 9
Transfer-Encoding: chunked

6
x=test --> front-end reads up to here
X --> back-end expects another chunk or completion of chunks

Since the back-end receives only the first chunk but not either the terminating 0 or another chunk, the back-end waits for more content, resulting in a time-out.

For a TE.CL vulnerability, triggering a timeout due to a request smuggling vulnerability would look like the following:

POST /test HTTP/1.1
Host: example.com
Content-Length: 11
Transfer-Encoding: chunked

0 --> Front-end reads up to here

x=test --> back-end expects content up to here due to the content-length header

Since the back-end only receives the content up to 0 but has specified a larger Content-Length, the back-end waits for more content, which leads to a time-out.

It is important to always check the vulnerabilities in the order CL.TE and then TE.CL, because if there is a CL.TE vulnerability with a TE.CL time-out request, it may disrupt other users of the web application.

If a request smuggling vulnerability has been identified by Burp’s ActiveScan or by manual testing, BurpSuite Pro provides the Turbo Intruder, which can be used to script and exploit the identified vulnerabilities. An example of this can be found in HackerOne Report 498052 for a CL.TE vulnerability in New Relic and F5, respectively.

It should also be noted that there is a possibility of false negatives when trying to exploit the vulnerability, as the hoped-for response may not end up with the tester, but with an unsuspecting user of the website. It should also be noted that false negatives can also occur when testing in a development or test environment, as these may not be behind the same load balancing setup as the production environment.

Countermeasures

It should be checked whether this vulnerability is already known in the product used and whether an update/patch is available for it. Since request smuggling vulnerabilities arise when request sizes are interpreted differently between a front end and a back end, this should be the starting point. The front-end should normalize requests that contain both the Content-Length and Transfer-Encoding headers chunked, so that only one of these headers is used. Nevertheless, if the back-end ever receives a request that contains both Content-Length and Transfer-Encoding chunked headers, the request should be discarded and the TCP connection closed. If the vulnerability occurred due to an HTTP/2 protocol downgrade, only HTTP/2 should be used throughout where possible to prevent this vulnerability from occurring in the first place.

Conclusion

Request smuggling is a very powerful vulnerability with far-reaching implications. It makes it possible to intercept sensitive or confidential information and exploit vulnerabilities that would otherwise be impossible to exploit. Accordingly, it is important to keep these implications in mind when testing, because if something is done incorrectly, all users of the tested website can potentially be affected. It should also be noted that a test for request smuggling cannot always provide a 100% statement about whether this vulnerability is actually present or not.

About the Author

Andrea Hauser

Andrea Hauser graduated with a Bachelor of Science FHO in information technology at the University of Applied Sciences Rapperswil. She is focusing her offensive work on web application security testing and the realization of social engineering campaigns. Her research focus is creating and analyzing deepfakes. (ORCID 0000-0002-5161-8658)

Links

Are you interested in a Penetration Test?

Our experts will get in contact with you!

×
Ways of attacking Generative AI

Ways of attacking Generative AI

Andrea Hauser

XML Injection

XML Injection

Andrea Hauser

Burp Macros

Burp Macros

Andrea Hauser

WebSocket Fuzzing

WebSocket Fuzzing

Andrea Hauser

You want more?

Further articles available here

You need support in such a project?

Our experts will get in contact with you!

You want more?

Further articles available here