Web cache poisoning
Constructing an attack
Identify unkeyed inputs (e.g.
X-Forwarded-Host
header)Trigger a harmful response from the server
Get the response cached
Hint: You can use "Param Miner" Burp Suite extension for automating the process of finding such inputs.
Exploitation
Websites are vulnerable when they:
Handle unkeyed input in an unsafe way
Allow the subsequent HTTP response to be cached
Unsafe handling of resource imports
If the X-Forwarded-Host
header is reflected for resource imports, you can point it to a domain you control and host a malicious file there, using the same path/name as the original one.
Result
Cookie-handling vulnerabilities
If the Cookie
header is unkeyed and uses a parameter that is reflected on the site, this can be used to inject malicous code.
Multiple headers required
Sometimes it is necessary to tamper with more than just one input.
E.g. setting X-Forwarded-Scheme
header to something different than the default scheme (https) may trigger the usage of X-Forwarded-Host
header. Therefore you can just inject a domain that is under your control, to serve a malicious file.
Responses exposing too much information
Response headers, like follows, may reveal a lot of information, how the cache behaves and therefore can save a lot of manual testing.
The Vary
response header may also tell about additional headers used in the caching key.
Cache implementation flaws
Methodology
Identify a cache oracle (e.g. http header that reveals cache hits, changes to dynamic content, response times variations)
Probe key handling (look for transformations, e.g. removing port from
Host
header)Identify an exploitable gadget (e.g. reflected XSS or open redirects)
Unkeyed port
You may be able to construct a DoS attack by specifying an arbitrary port, that is then served to all users, until the cache expires.
Using a non-numeric port, you may even be able to serve XSS payloads.
Unkeyed query string
If the query string is not keyed and vulnerable to e.g. reflected XSS, your XSS payload will be served to any user accessing that site, once you poisoned the cache.
Unfortunately, as the query string is unkeyed, it cannot be used as a cache buster.
Gladly, there are alternative cache busters, like:
Common headers, e.g.:
Accept-Encoding
,Accept
,Cookie
,Origin
(subdomain)Using discrepancies between backend and cache, e.g. modifiying the path to
//
(Apache),/%2F
(nginx),/index.php/xyz
(PHP),/(A(xyz)/
(.NET)
Unkeyed query parameters
Basically the same as "Unkeyed query string", but only part of the query string is unkeyed (e.g. specific parameters, like utm_
analytics/tracking parameters).
Parameter cloaking
Potenial attack surfaces appear, when there are disceprancies between the cache and the application.
Examples:
Poor written parsing algorithms may treat any
?
as the start of a new parameter.Ruby on Rails interprets both
&
and;
as parameter delimiters, but maybe the cache does not.
Fat GET support
Sometimes the HTTP method may not be keyed. Therefore you could poison the cache with a
POST
request containing a malicious body, which will then also be served for users invokingGET
requests.Pretty rare, but sometimes you can also just add a body to a
GET
request.
Normalized cache keys
When a cache normalizes keyed input, it can lead to exploitable behavior. Ocassionally even to exploits that would otherwise be almost impossible.
Poison the cache with your payload.
Deliver a url encoded version to your victim, which then will be served with the poisened version from the cache.
Last updated