siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

Exploiting path delimiters for web cache deception

Table of Contents

  1. Overview
  2. Background
  3. Enumeration
    3.1 Delimiter Discrepancies
    3.2 Exploiting Delimiter Discrepancies
  4. Exploitation
  5. Conclusion

Overview

Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Exploiting path delimiters for web cache deception! Without further ado, let’s dive in.

Background

To solve the lab, find the API key for the user carlos. You can log in to your own account using the following credentials: wiener:peter.

We have provided a list of possible delimiter characters to help you solve the lab: Web cache deception lab delimiter list.

Enumeration

Index page:

Burp Suite HTTP history:

In here, we can see that some static resources were cached. Maybe we could do something with this.

Login page:

Let’s login as user wiener:

After logging in, we can see our API key.

In this lab, our goal is to steal user carlos’s API key.

In the previous lab, we leveraged the discrepancies between the RESTful URL path mapping and cache path mapping.

Are there anymore ways to abuse this type of discrepancies to exploit web cache deception?

Delimiter Discrepancies

Delimiters specify boundaries between different elements in URLs. The use of characters and strings as delimiters is generally standardized. For example, ? is generally used to separate the URL path from the query string. However, as the URI RFC is quite permissive, variations still occur between different frameworks or technologies.

Discrepancies in how the cache and origin server use characters and strings as delimiters can result in web cache deception vulnerabilities. Consider the example /profile;foo.css:

The same is true for other characters that are used inconsistently between frameworks or technologies. Consider these requests to an origin server running the Ruby on Rails framework, which uses . as a delimiter to specify the response format:

Encoded characters may also sometimes be used as delimiters. For example, consider the request /profile%00foo.js:

Exploiting Delimiter Discrepancies

We may be able to use a delimiter discrepancy to add a static extension to the path that is viewed by the cache, but not the origin server. To do this, we’ll need to identify a character that is used as a delimiter by the origin server but not the cache.

Firstly, find characters that are used as delimiters by the origin server. Start this process by adding an arbitrary string to the URL of our target endpoint. For example, modify /settings/users/list to /settings/users/listaaa. We’ll use this response as a reference when we start testing delimiter characters.

Note

If the response is identical to the original response, this indicates that the request is being redirected. We’ll need to choose a different endpoint to test.

Next, add a possible delimiter character between the original path and the arbitrary string, for example /settings/users/list;aaa:

Once we’ve identified delimiters that are used by the origin server, test whether they’re also used by the cache. To do this, add a static extension to the end of the path. If the response is cached, this indicates:

Make sure to test all ASCII characters and a range of common extensions, including .css, .ico, and .exe. Use Burp Intruder to quickly test these characters. To prevent Burp Intruder from encoding the delimiter characters, turn off Burp Intruder’s automated character encoding under Intruder > Payloads > Payload encoding.

We can then construct an exploit that triggers the static extension cache rule. For example, consider the payload /settings/users/list;aaa.js. The origin server uses ; as a delimiter:

The origin server returns the dynamic profile information, which is stored in the cache.

Because delimiters are generally used consistently within each server, we can often use this attack on many different endpoints.

Note

Some delimiter characters may be processed by the victim’s browser before it forwards the request to the cache. This means that some delimiters can’t be used in an exploit. For example, browsers URL-encode characters like {, }, <, and >, and use # to truncate the path.

If the cache or origin server decodes these characters, it may be possible to use an encoded version in an exploit.

Let’s try this!

First, we’ll need to find the characters that are used as delimiters by the origin server. To do so, we can adding an arbitrary string to the URL of our target endpoint, such as from /my-account to /my-accountfoobar:

As we can see, if we append arbitrary string to /my-account, the server respond HTTP status code “404 Not Found”.

Now, if we insert an arbitrary string between /my-account and foobar, non HTTP status code “404 Not Found” is the delimiter by the origin server.

To find the delimiter, we can fuzz the path via Burp Suite’s Intruder:

Then, copy and paste the delimiter characters into the payload settings:

Next, uncheck payload encoding:

Finally, click “Start attack”:

After fuzzing, we can see that characters ; and ? respond HTTP status code “200 OK”:

Since ? is the URL query syntax, we can ignore that. Therefore, character ; is the delimiter by the origin server.

Now we found that the delimiter is ;, we can process to find which extensions are used by the cache.

To do so, we can fuzz the extensions, such as .js, .css, .ico, and more. After trying, we can see the .js indeed get cached:

Which contains the API key:

Exploitation

Armed with the above information, we can steal carlos’s API key via:

  1. Trick the victim to visit /my-account;foobar.js to cache the API key response
  2. We, attacker, go to /my-account;foobar.js to get the cached response

We can try to test this:

Note: The cachebuster parameter is for testing purposes.

Then, before the cache expired, remove the Cookie request header and send the request again:

Nice!

Now we can go to our exploit server, and change the response header to this:

HTTP/1.1 301 Moved Permanently
Location: https://0a2f00fa047523c9809db26c00c4003d.web-security-academy.net/my-account;foobar.js

Then click button “Deliver exploit to victim”. This will trick the victim to cache their API key response:

Finally, send the following request to retrieve the cached response:

GET /my-account;foobar.js HTTP/2
Host: 0a2f00fa047523c9809db26c00c4003d.web-security-academy.net


We got carlos’s API key! Let’s submit it to solve this lab!

Conclusion

What we’ve learned:

  1. Exploiting path delimiters for web cache deception