Web Cache Poisoning
Last updated
Last updated
Caching is intended to speed up page loads by reducing latency, and also reduce load on the application server.
Varnish
Cloudflare(caches scattered across geographical locations.)
Drupal have a built-in cache.
Request is being received by Cache
Cache Checks whether it has a copy of this exact resource being requested then it response with it
If not ,Cache forwards the request to the application server.
byte-for-byte compare.(ineffective)
📌 Caches tackle this problem using the concept of cache keys
URL and it’s Get parameters
Host header
Based on those 2 Keys Cache Will handle The next 2 Requests in the same way
📌 As a result, the page will be served in the wrong language to the second visitor.
Vary response header is Used to specify additional request headers that should be keyed.But it’s used in a rudimentary way.
📌 is to send a request that causes a harmful response that gets saved in the cache and served to other users.
Identify unkeyed inputs(Manually Or Using Param miner or any other fuzzing tool)
📌 Cached responses can mask unkeyed inputs - The response is the same thus,you can’t notice the unkeyed inputs.Changing it while testing won’t be effective(it’s already cached) Therefore,using a cache-buster would help If you test manually. or you can ensure every request has a unique cache key by adding a parameter with a value of $randomplz to the query string or in your fuzzing tool.
Identify how much damage you can do with it.
Try and get it stored in the cache
📌 To keep it legal,Cache The request using a get parameter with a fixed value just to affect your requests while testing.
In most cases this is just a self-xss
dontpoisoneveryone=1 is our cache-buster in this case.
The response headers 'Age' and 'max-age' respectively specify the age of the current response, and the age at which it will expire.the response expires when the age == max-age.
Sometimes you notice the max-age is missing but at some point the server will reset the age.
Find when by automating requests in different times and observing the response.
Or you can just spam your malicious request using burp intruder.
As seen in the response,The User-Agent is being used as a key for cache.
So you might poison it with the most used user agents.
If you are targeting someone(selective) you can just poison the cache with his user agent
anyone with that user agent will be affected.
Sometimes it’s not about just an XSS payload,it’s complicated somehow,
an example :
Some applications use headers for internal request routing
📌 HubSpot is giving the X-Forwarded-Server header priority over the Host header
Go to HubSpot,Create a web page, paste its URL into the X-Forwarded-Server,
Your response would be your web page and should be cached and served to all users,it’s sound like an subdomain take over.
📌 Cloudflare's blog is hosted by Ghost, who are clearly doing something with the X-Forwarded-Host header.
Example Found on [1][”Hidden Route Poisoning:”]
We might chain 2 headers
A good combination of
📌 the application sets 'Cache-Control: private', and Cloudflare refuse to cache such responses. Fortunately, other pages on the site explicitly enable caching.📌 The 'CF-Cache-Status' header is an indicator that Cloudflare is considering caching this response.📌 Cloudflare have even more regional caches📌 I suspect that quite a few websites start using a service like Cloudflare for DDoS protection or easy SSL, and end up vulnerable to cache poisoning simply because caching is enabled by default.
📌 X-Original-URL and X-Rewrite-URL which override the request's path
📌 Which might be used to convert reflected XSS into stored XSS some times.Something Like that:(**Internal Cache Poisoning)**
📌 If the site uses an external cache.we can use the internal cache to poison the external cache
This web application is using a caching system. By sending a GET request with a request body (a "fat" GET request) it was possible to force the caching system to cache a response that contains user-controlled input.
Activate “Add fcbz cachebuster”.while testing your payloads that you want it to be cached
Activate “Add Dynamic cachebuster” while guessing the used inputs.
Ibrahim Radi
After Performing the Basic Poisoning on /en?dontpoisoneveryone=1,We would like to perform it on the homepage now.Which would be normally cached ,Therefore you need to wait to cache Your malicious request when the last cached request is over.
is a protocol created by Facebook to let website owners dictate what happens when their content is shared on social media. The og:url parameter we've hijacked here effectively overrides the URL that gets shared, so anyone who shares the poisoned page actually ends up sharing content of our choice.