Exploiting exact-match cache rules for web cache deception
Table of Contents
- Overview
- Background
- Enumeration
3.1 Exploiting File Name Cache Rules
3.2 Detecting Normalization By the Origin Server
3.3 Detecting Normalization By the Cache Server
3.4 Exploiting Normalization Discrepancies - Exploitation
- Conclusion
Overview
Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Exploiting exact-match cache rules for web cache deception! Without further ado, let’s dive in.
- Overall difficulty for me (From 1-10 stars): ★★★★★☆☆☆☆☆
Background
To solve the lab, change the email address for the user administrator
. 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:
Login page:
Let’s login as user wiener
:
After logging in, we can view our profile page.
Burp Suite HTTP history:
When we logged in, it’ll send a POST request to /validateSession
with parameter csrf
.
We can also update our email:
More over, in our Burp Suite HTTP history, we can see that resource /favicon.ico
was cached:
Exploiting File Name Cache Rules
Certain files such as robots.txt
, index.html
, and favicon.ico
are common files found on web servers. They’re often cached due to their infrequent changes. Cache rules target these files by matching the exact file name string.
To identify whether there is a file name cache rule, send a GET
request for a possible file and see if the response is cached.
Detecting Normalization By the Origin Server
To test how the origin server normalizes the URL path, we can 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, we can modify /my-account
to /anything/..%2fmy-account
:
As you can see, it respond HTTP status code “404 Not Found”, which means the path has been interpreted as /anything/..%2fmy-account
. The origin server either doesn’t decode the slash or resolve the dot-segment.
Detecting Normalization By the Cache Server
Same as detecting normalization by the origin server, we can 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, we can cache /favicon.ico
. Then send path /anything/..%2f/favicon.ico
:
As you can see, the response is still cached, this may indicate that the cache has normalized the path from /anything/..%2f/favicon.ico
to /favicon.ico
.
Exploiting Normalization Discrepancies
Because the response is only cached if the request matches the exact file name, we can only exploit a discrepancy where the cache server resolves encoded dot-segments, but the origin server doesn’t.
To do so, we can construct a payload according to the following structure: /<dynamic-path>%2f%2e%2e%2f<static-directory-prefix>
.
However, since the origin server is likely to return an error message instead of profile information, we’ll need to also identify a delimiter that is used by the origin server but not the cache. Test possible delimiters by adding them to the payload after the dynamic path.
After fuzzing by hand, we can find that character ;
is the delimiter:
This path /my-account;%2f%2e%2e%2ffavicon.ico
resulted in different result in the origin and cache server:
- The cache interprets the path as:
/favicon.ico
- The origin server interprets the path as:
/my-account
What now? What we can do with this web cache deception vulnerability?
Maybe we can steal the CSRF token, and then change the victim’s email address via exploiting CSRF??
Exploitation
Let’s try to cache the victim’s profile page, and see what’ll happen.
First, modify the response header to this:
HTTP/1.1 301 Moved Permanently
Location: https://0ab6002d0430479d8014a882002800d7.web-security-academy.net/my-account;%2f%2e%2e%2ffavicon.ico
Then, click button “Deliver exploit to victim”:
After that, before the cache expired, go to /my-account;%2f%2e%2e%2ffavicon.ico
to visit the cached response:
As you can see, the victim in this case is administrator
and we got the CSRF token.
After the second try, the CSRF token didn’t change at all.
With that said, we can use administrator
’s CSRF token to update his email!
CSRF Payload:
<form id="csrfForm" name="change-email-form" action="https://0aae002f0480e270c92ee04100ba0094.web-security-academy.net/my-account/change-email" method="POST">
<label>Email</label>
<input required type="email" name="email" value="pwned@attacker.com">
<input required type="hidden" name="csrf" value="heM6rtv6eAHoC8r1Jl9EKMWjLBdRb2aq">
<button class='button' type='submit'> Update email </button>
</form>
<script>
csrfForm.submit();
</script>
This payload will automatically submit the update email form upon visiting.
Remember to change the response header to serve our payload:
HTTP/1.1 200 OK
Content-Type: text/html
Finally, send our CSRF payload to the victim via the “Deliver exploit to victim” button:
Conclusion
What we’ve learned:
- Exploiting exact-match cache rules for web cache deception