Web cache poisoning

Web cache poisoning uses a variety of methods to sneak modified (usually malicious) data into a web cache and have it returned to a client instead of legitimate cached content.

Modifying cache content is not an attack in itself but just a technique for delivering payloads, making web cache poisoning as dangerous as the underlying vulnerability that is targeted. While not easy to do, it can also be hard to detect and troubleshoot, making it an interesting tool for attackers and an important point for penetration testing and bug hunting.

Steps

  1. Check what kind of caching is used and detect web cache hits and misses.

  2. Identify and evaluate unkeyed inputs.

  3. Web cache poisoning attacks are only possible when these inputs can be used to generate other responses dynamically or if the server reflects this input in its response without adequate validation or input sanitation. understand how the web server processes the unkeyed input to elicit a malicious response from the back-end server successfully.

  4. Get the response cached: The success of a web caching attack depends on the successful storage of the harmful response in cache memory. Use trial & error to examine the behaviour of the cache.

Unkeyed inputs

  • Reflected unkeyed headers: If the application directly reflects the value of an unkeyed header in the response, it opens the door to cache poisoning. Its value is not part of the cache key. If the attacker sends a request where only this header is maliciously modified, the response to this request will be cached, with the malicious payload targeting, for example, an XSS vulnerability. Users subsequently requesting content that matches the same cache key will receive the malicious version from the cache.

  • Unkeyed port: If the port is not part of the cache key, it may be possible to perform a denial of service (DoS) attack by poisoning the cache with an inaccessible port number. If an attacker sends a request that includes such a port number and the error response is cached, users requesting the same URL without the port will immediately get the cached error instead of the expected page content. This will render the page inaccessible to users.

  • Unkeyed request method: Sometimes the HTTP request method (GET, POST, PUT, etc.) is not be part of the cache key. If the application is also vulnerable to parameter pollution, it may be possible to send a POST request containing a malicious payload that modifies a parameter for an XSS attack. The poisoned response will then be cached and because the cache key does not account for the HTTP method, it will be delivered to clients that send a normal GET request matching the same cache key.

  • Unkeyed query string: If the query string of a request is unkeyed and reflected in the response, it may be possible to inject a malicious payload into a query parameter and cache the response. Clients sending a matching request with no query string would then receive the poisoned response. Because the attack is a typical script injection, it effectively turns a reflected XSS into a stored XSS, with the script stored in the web cache. If used directly, it is not hard to detect, but it may evade detection in more complex scenarios.

Fat GET requests

If an application accepts non-standard GET requests that have a body (making them fat) and the request body is unkeyed and reflected in the response, it may be possible to include a malicious payload in the GET request, and the response will be cached (because the request body is not part of the key). Users sending a regular GET request that matches the same cache key will receive the poisoned response. In some cases, it may also be possible to use the X-HTTP-Method-Override header to trick the application into treating a fat GET request as a normal POST request.

Cache busting

A cache-buster is a unique piece of code that prevents a browser from reusing an element it has already seen and cached, or saved, to a temporary memory file.

GET /?parameter1=whatever&parameter2=evil HTTP/1.1

A cache-buster doesn’t stop a browser from caching an element, it just prevents it from reusing it.

For dual caches, Burp’s param miner can add a dynamic cache buster to each request made, which can be helpful for bypassing one cache and focusing on the other.

Escalation

The impact of web cache poisoning is heavily dependent on several key factors: What can successfully get cached, the amount of traffic on the affected page, and for more targeted attacks, who is likely to visit the poisoned page.

Variants

The inputs that open this up are unkeyed headers, cookies, query strings, and individual query parameters reflected into the response, along with parameter cloaking, fat GET requests, and cache key injection. The harder cases reach an internal cache, exploit a DOM sink through a cache with strict cacheability criteria, or chain several unkeyed inputs together. The web cache poisoning runbook works through reading the cache, finding the unkeyed input, and landing the payload.

Resources

Counter moves

Web cache poisoning is what this page works through. These come back to the same answers: validated input, encoded output, server-side authorisation, and patched dependencies. The defender’s view can be found in the blue notes on the application layer as a target.