Prompt Injection
Andrea Hauser
This is how Request Smuggling works
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.
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: chunked6 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.
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.
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}
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
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
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:
:
between transfer encoding and chunked.:
between transfer encoding and chunkedAn 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.
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.
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.
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.
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.
Our experts will get in contact with you!
Andrea Hauser
Andrea Hauser
Andrea Hauser
Andrea Hauser
Our experts will get in contact with you!