siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

Exploiting origin server normalization for web cache deception

Table of Contents

  1. Overview
  2. Background
  3. Enumeration
    3.1 Exploiting Static Directory Cache Rules
    3.2 Normalization Discrepancies
    3.3 Detecting Normalization By the Origin Server
    3.4 Detecting Normalization By the Cache Server
    3.5 Exploiting Normalization By the Origin Server
  4. Exploitation
  5. Conclusion

Overview

Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Exploiting origin server normalization 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 being cached.

Login page:

Let’s login as user wiener:

After logging login, we can view our API key:

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

In previous labs, we exploited the discrepancies in the URL path mapping and path delimiters.

Exploiting Static Directory Cache Rules

It’s common practice for web servers to store static resources in specific directories. Cache rules often target these directories by matching specific URL path prefixes, like /static, /assets, /scripts, or /images. These rules can also be vulnerable to web cache deception.

Normalization Discrepancies

Normalization involves converting various representations of URL paths into a standardized format. This sometimes includes decoding encoded characters and resolving dot-segments, but this varies significantly from parser to parser.

Discrepancies in how the cache and origin server normalize the URL can enable an attacker to construct a path traversal payload that is interpreted differently by each parser. Consider the example /static/..%2fprofile:

As shown in the above example, each dot-segment in the path traversal sequence needs to be encoded. Otherwise, the victim’s browser will resolve it before forwarding the request to the cache. Therefore, an exploitable normalization discrepancy requires that either the cache or origin server decodes characters in the path traversal sequence as well as resolving dot-segments.

Detecting Normalization By the Origin Server

To test how the origin server normalizes the URL path, send a request to a non-cacheable resource with a path traversal sequence and an arbitrary directory at the start of the path. To choose a non-cacheable resource, look for a non-idempotent method like POST. For example, modify /profile to /aaa/..%2fprofile:

Note

When testing for normalization, start by encoding only the second slash in the dot-segment. This is important because some CDNs match the slash following the static directory prefix.

We can also try encoding the full path traversal sequence, or encoding a dot instead of the slash. This can sometimes impact whether the parser decodes the sequence.

In our case, we can try to send a POST request to /anything/..%2fmy-account:

As you can see, it respond to us with HTTP status code “200 OK”. That being said, the origin server decodes the slash and resolves the dot-segment.

Detecting Normalization By the Cache Server

We can use a few different methods to test how the cache normalizes the path. Start by identifying potential static directories. In Proxy > HTTP history, look for requests with common static directory prefixes and cached responses. Focus on static resources by setting the HTTP history filter to only show messages with 2xx responses and script, images, and CSS MIME types.

We can then choose a request with a cached response and resend the request with a path traversal sequence and an arbitrary directory at the start of the static path. Choose a request with a response that contains evidence of being cached. For example, /aaa/..%2fassets/js/stockCheck.js:

We can also add a path traversal sequence after the directory prefix. For example, modify /assets/js/stockCheck.js to /assets/..%2fjs/stockCheck.js:

Note that in both cases, the response may be cached due to another cache rule, such as one based on the file extension. To confirm that the cache rule is based on the static directory, replace the path after the directory prefix with an arbitrary string. For example, /assets/aaa. If the response is still cached, this confirms the cache rule is based on the /assets prefix. Note that if the response doesn’t appear to be cached, this doesn’t necessarily rule out a static directory cache rule as sometimes 404 responses aren’t cached.

Note

It’s possible that we may not be able to definitively determine whether the cache decodes dot-segments and decodes the URL path without attempting an exploit.

In our case, we can try to add a path traversal sequence after the directory prefix, such as from /anything/resources/js/tracking.js to /anything/..%2fresources/js/tracking.js:

As you can see, the response is no longer cached, which means the cache isn’t normalizing the path before mapping it to the endpoint. It shows that there is a cache rule based on the /resources/ prefix.

Exploiting Normalization By the Origin Server

If the origin server resolves encoded dot-segments, but the cache doesn’t, we can attempt to exploit the discrepancy by constructing a payload according to the following structure: /<static-directory-prefix>/..%2f<dynamic-path>.

For example, consider the payload /assets/..%2fprofile:

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

In our case, we can exploit the discrepancy by the following payload:

GET /resources/..%2fmy-account HTTP/2
Host: 0aa1004104cb94ff80c4ee10001a0010.web-security-academy.net


In here, the cache interprets the path as /resources/..%2fmy-account, and the origin server interprets it as /my-account:

Exploitation

Armed with above information, we can steal carlos’s API key via the discrepancy in normalization by the origin server. To do so, we can:

  1. Trick the victim to visit /resources/..%2fmy-account, which caches the response of the API key
  2. We, attacker, visit /resources/..%2fmy-account to retrieve the cached response

We can also test it before exploiting it on the victim side.

Send the following request:

Then remove the Cookie request header:

As you can see, we successfully retrieved the cached response’s API key.

Now, to get carlos’s API key, we can:

Modify the response header to the following:

HTTP/1.1 301 Moved Permanently
Location: https://0aa1004104cb94ff80c4ee10001a0010.web-security-academy.net/resources/..%2fmy-account

Then click button “Deliver exploit to victim”:

Next, send a GET request to /resources/..%2fmy-account:

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

Conclusion

What we’ve learned:

  1. Exploiting origin server normalization for web cache deception