Lab: Exploiting cache server normalization for web cache deception
Identify a target endpoint
Once we have successfully logged in to the exercise, the blog should look like the following image. We click on the link "My account" and log in to the application with the user name wiener and the password peter.

After logging in, we have access to the account of wiener and see an API key.

Investigate path delimiters used by the origin server
We now switch to the Burp Proxy and open the "HTTP history" tab there. In the "HTTP history", search for the request GET /my-account and send it to Burp Repeater.

To send the request to Burp Repeater, move the mouse over the request and press the right mouse button. A context menu appears in which we select the option "Send to Repeater".

We now switch to the burp repeater and insert any character string in the first line. The request could look like this.
We now send the request to the application and receive the following response.
As we can see, our sent path could not be found on the server. We also do not receive any information about whether data is delivered by caches. This means that the origin server does not abstract the path to /my-account.
Now we remove our appended character string and add it to the original path. GET /my-account/abc now becomes GET /my-accountabc. The request should now look like this.
We send the request to the application and receive the same response as from the previous attempt.
We now send the request to the Burp Intruder. To do this, we move the mouse over the request and press the right mouse button, in the context menu we select the option "Send to Intruder".

Now switch to the Burp Intruder and check whether the attack type is set to "Sniper attack". This should be the case if you have restarted Burp for this exercise, as this is the default setting.

Now we insert a payload position in our path. To do this, click with the mouse between /my-account and abc and click on the "Add" button.

In the next step, we go back to the start page of this exercise and copy the list of limiters.

The list can be found in the following code block.
The "Payloads" section is located on the right-hand side of the Burp Intruder. In the subsection "Payload configuration" we paste the list of limiters we just copied. To do this, we click on the "Paste" button.

In the subsection "Payload encoding" we deactivate the checkbox "URL-encode these characters". If we do not disable this option, Burp Intruder will encode our delimiters and we will not be able to identify any delimiters used by the application.

In the result window, we now click twice on the "Status code" column and see that the characters #, ?, %23 and %3f have received a 200 OK code. This indicates that the origin server only uses ? as a path delimiter. This means that they are used as path delimiters by the origin server. Ignore the # character. It cannot be used for an exploit because the victim's browser uses it as a delimiter before forwarding the request to the cache.
If you are using the Community Edition of Burp, this attack may take a little longer, as the Burp Intruder version is somewhat limited.
Investigate path delimiter discrepancies
We now switch to the Burp Repeater and add a static file extension to our string. To do this, we use the extension .js for JavaScript files. The request could look like this.
After sending the request, we receive the following response.
The answer contains no reference to caching. This indicates either that the cache also uses ? as a path delimiter, or that the cache does not have a rule based on the .js extension.
We now test the limiter %23 and add it to our request. The request should look like this.
After sending the request, we receive the following response.
The response contains no reference to caching. This indicates either that the cache also uses %23 as a path delimiter, or that the cache does not have a rule based on the .js extension.
We now test the %3f delimiter and add it to our request. The request should look like this.
After sending the request, we receive the following response.
The answer contains no reference to caching. This indicates either that the cache also uses %3f as a path delimiter, or that the cache does not have a rule based on the .js extension.
Investigate normalization discrepancies
In the repeater, we now remove the character string abc.js from the request and insert a directory with an attached coded point sequence /aaa/..%2fmy-account. The request should look like this.
We send the request to the application and receive the response '404 Not Found'. This indicates that the origin server is not decoding or resolving the dot segment to normalise the path to /my-account.
Now we switch to the "HTTP history" tab in the Burp Proxy and see that static files all start with the prefix /resources.

We now send any request with the prefix /resources to the Burp Repeater. In this example, we use the request GET /resources/js/tracking.js.

In Burp Repeater, we now send this request to the application and look at the response. We see indications of caching here.

Now we place the coded point sequence (/aaa/..%2) before the prefix (/resource) in the first line of our request. The first line of our request should therefore look like this: /aaa/..%2resources/js/tracking.js. The complete one is shown below.
When we send this request, we receive a 404 Not Found response, with the header X-Cache: miss. If we send the request to the application again within 30 seconds, the value of the header is X-Cache: hit. This may indicate that the cache is decoding and resolving the point sequence and has a cache rule based on the prefix /resources. To confirm this, you will need to perform further tests. It is still possible that the response is cached due to a different cache rule.
Now we place the coded point sequence after the prefix /resources and the request looks like this.
When we send the request to the application, we again receive a 404 Not Found. This time, however, there is no indication of caching in the response. This means that the cache decodes and resolves the dot segment and has a cache rule based on the prefix /resources.
Craft an exploit
We now switch to the Burp Repeater and open the tab with the request /aaa/..%2fmy-account. With the limiter ? we now try to construct an exploit that looks like this.
We have now URL-encoded the complete point sequence. If we send this request to the application, we receive our API key, but no information about caching.
Now we use %3f as a delimiter and send the following request to the application.
Again, we receive our API key, but no information about caching.
Now let's try %23 as a limiter.
In the response we now see the headers Cache-Control: max-age=30, Age: 0 and X-Cache: miss. If we send the request again within 30 seconds, the header X-Cache contains the value hit.
We now open our exploit server by clicking on the "Go to exploit server" button.

In the Exploit Server, we scroll down to the "Body" section.

We insert the following exploit code there. This code redirects the victim carlos to a malicious URL. At the end, we insert an arbitrary value as a cache buster (wcd) so that carlos does not receive the previously cached response.
The URL must be adapted to your environment.
We now click the button "Deliver exploit to victim".

Now we copy the URL from the exploit https://0a8c0036038e212980ae627e00f300a1.web-security-academy.net/my-account%23%2f%2e%2e%2fresources?wcd and paste it into a new tab in the browser. We now see the account of carlos.

The exploit may have to be delivered to the victim several times before access to the account of carlos is possible.
We now copy the API key (bBfNzXXta0i9LuulsNFRfn40isN06fmk) from carlos and click on the "Submit solution" button.

In the window, we paste the API key we just copied from carlos and click on "Ok".

The exercise was successfully completed.

Video solution
Last updated