Web cache poisoning via a fat GET request | Jan 25, 2023
Introduction
Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Web cache poisoning via a fat GET request! Without further ado, let’s dive in.
- Overall difficulty for me (From 1-10 stars): ★☆☆☆☆☆☆☆☆☆
Background
This lab is vulnerable to web cache poisoning. It accepts GET
requests that have a body, but does not include the body in the cache key. A user regularly visits this site’s home page using Chrome.
To solve the lab, poison the cache with a response that executes alert(1)
in the victim’s browser.
Exploitation
Home page:
Burp Suite HTTP history:
In here, we see that the web application is using caches to cache the web content.
Also, it has a canonical <link>
element, which pointing to a domain, and an <script>
element.
/js/geolocate.js
:
const setCountryCookie = (country) => { document.cookie = 'country=' + country; };
const setLangCookie = (lang) => { document.cookie = 'lang=' + lang; };
setCountryCookie({"country":"United Kingdom"});
Now, we can test the canonical <link>
element is generated dynamically or not:
Yes, it’s dynamically generated!
Let’s test the string query is keyed or not:
When we get a cache hit, then remove the query string, it won’t get reflected to the web page.
That being said, query strings are keyed, and we couldn’t poison the cache.
How about the geolocate.js
?
Hmm… The callback
parameter is not unkeyed…
However, the HTTP method may not be keyed. This might allow us to poison the cache with a POST
request containing a malicious payload in the body. Our payload would then even be served in response to users’ GET
requests. Although this scenario is pretty rare, we can sometimes achieve a similar effect by simply adding a body to a GET
request to create a “fat” GET
request!
As you can see, our “fat” GET request has been taken from the server-side! Hence, it’s unkeyed!
Armed with above information, we can poison the cache with an evil JavaScript function:
When a victim visit the website, it’ll triggered our XSS payload:
What we’ve learned:
- Web cache poisoning via a fat GET request