Browser-Powered Request Smuggling - New Request Smuggling Technique

Browser-Powered Request Smuggling

New Request Smuggling Technique

Andrea Hauser
by Andrea Hauser
on October 20, 2022
time to read: 6 minutes

Keypoints

This is how Browser-Powered Request Smuggling works

  • New Research shows that Request Smuggling is not only possible between a chain of servers
  • CL.0 also known as client-side desync desynchronises the connection between a victim's browser and the server
  • static content and redirects are particularly vulnerable
  • tooling already exists to detect these new vulnerabilities in a straightforward way

Browser-powered request smuggling allows new client-side variations of request smuggling, which allows not only attacking a chain with multiple servers but also a standalone server. Compared to the previously shown request smuggling attacks, the issued requests are well-formed and can therefore be sent via a browser. Attacking a single server is possible since the attack is laid out to get a victim’s browser to poison its own connection to a vulnerable server.

This article is heavily based on research from James Kettle that was presented on Defcon 30. Based on this research multiple labs on the topic client-side desync were created in the Portswigger Web Academy. Those labs can be used to attempt the attacks in practice.

CL.0 Request Smuggling

The previously covered request smuggling attacks were all based on achieving different interpretations of requests between several servers in a chain by means of content length and transfer encoding headers manipulation. The CL.0 attack works because certain servers assume that the request does not contain a body and therefore assume a content length of 0. If the back-end server always assumes a content length of 0, but the front-end server accepts the content length given, this can lead to discrepancies. Testing whether a CL.0 vulnerability exists is very simple.

POST /vulnerable-endpoint HTTP/1.1
Host: example.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 33 --> valid Content-Length

GET /shouldBe404 HTTP/1.1
Foo: x

The above is a complete request with a valid content length that contains a second incomplete request in the body. If a 404 response is received in the response to a second valid request, which was sent shortly after this first submitted request, it can be assumed that a CL.0 request smuggling vulnerability is present. The CL.0 vulnerability can be used to exploit the same vulnerabilities as shown in the last labs. Endpoints that do not expect a POST request, for example static files or redirects, are most susceptible to CL.0 vulnerabilities.

Client-Side Desync Attacks

So far, request smuggling attacks have been considered a server-side problem, as they were misunderstandings between several servers in a chain. These could not be triggered from the browser, as they deliberately use manipulated or invalid requests. With the discovery of the CL.0 vulnerability, however, there is now the possibility to trigger attacks from a browser as well, since the CL.0 vulnerability involves requests that are not invalid, which means they can be issued by a browser. A client-side desync attack is the exploitation of a vulnerability in which the connection between the browser and a server is desynchronized. Accordingly, new attack paths open up, as it is no longer only a chain of servers that can be attacked, but also standalone or individual servers.

To abstract, a client-side desync attack consists of the following steps:

  1. The target of the attack is tricked into visiting an arbitrary web page running attacker-controlled JavaScript.
  2. The JavaScript triggers a request to the web page with the client-side desync vulnerability, leaving an uncompleted, malicious or for an attacker interesting request in the pipeline.
  3. This unfinished request remains in the pipeline between the browser and the request after the initial request has been answered. This desynchronizes the connection between browser and server.
  4. The JavaScript now triggers another request to the server, which extends the already started request with the victim’s cookies.

This is how it looks in code:

<html>
<script>
fetch('https://example.com/vulnerable-endpoint', {
    method: 'POST',
    body: 'GET /thisShouldBe404 HTTP/1.1\\r\\nFoo: x',
    credentials: 'include' // is set so that the "with-cookies" connection pool is used for the connection
}).then(() => {
    location = 'https://example.com/' // here the desynchronized connection is used
})
</script>
</html>

After visiting this website in a browser, two requests should be visible in the network tab. If the attack was successful, the second request, which is normally answered with a 200 OK, is answered with a 400 Bad Request. This example can be used to verify a client-side desync vulnerability. For an actual attack, the attacker would define a request in the body that stores the content of the victim’s second desynchronized request in the attacker’s account. This would allow the attacker to access the victim’s cookies and take over the victim’s session.

However, the example shown above does not work in all cases, for when a server-side redirect is triggered, the code area defined in the .then() block is not executed, instead the browser follows the redirect. To prevent the redirect and ensure that the client-side desync attack works, the following code can be used.

<html>
<script>
fetch('https://example.com/redirect-endpoint', {
    method: 'POST',
    body: 'GET /thisShouldBe404 HTTP/1.1\\r\\nFoo: x',
    mode: 'cors', // is set deliberately so that an error is thrown, and the redirect is cancelled
    credentials: 'include'
}).catch(() => {
    // here the CORS error is caught, and the desynchronized connection is used
    fetch('https://example.com/', {
        mode: 'no-cors',
        credentials: 'include'
    })
})
</html>
</script>

As in the previous example, after visiting this website in a browser, two requests should be visible in the network tab. If the attack was successful, the second request, which is normally answered with 200 OK, is answered with 400 Bad Request. A comprehensive step-by-step guide on how to test for client-side vulnerabilities can be found in the Portswigger Web Academy.

Conclusion

With client-side desync attacks, the field for request smuggling expands again and it can lead to more interesting attack scenarios, since now attacks against standalone servers are possible. The consequences of such attacks can be devastating, since the sessions of users can be taken over. Since the research was conducted by James Kettel, who is employed by Portswigger, the tooling for finding these new vulnerability types is already excellent, as current versions of Burp already have built-in identification for these vulnerabilities. For extended coverage, the HTTP Request Smuggler extension is recommended.

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!

×
Prototype Pollution

Prototype Pollution

Andrea Hauser

HTTP/2 Request Smuggling

HTTP/2 Request Smuggling

Andrea Hauser

Request Smuggling

Request Smuggling

Andrea Hauser

JWT Issues

JWT Issues

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