Skip to content

Web Cache Poisoning

The objective of web cache poisoning is to send a request that causes a harmful response that gets saved in the cache and served to other users.

There are different approaches to cache poisoning. One method involves attacking the intermediate web cache by taking over the origin server temporarily, then serving compromised content marked to be cached for an extended period of time.

The other method involves attacking the intermediate web cache server by disrupting the synchronization of the HTTP request and response streams between the origin server and web cache. Here the attacker may use HTTP response splitting to pass malicious content to the vulnerable web application, mostly through an HTTP request. The content is then included in an HTTP response header, usually sent to the user without validation.

Full size image

How to

An attacker might be able to poison a URL by sending an HTTP request to the site that causes the affected backend to respond with an attacker-controlled response. The malicious response object would be stored in the site’s cache at a poisoned URL. An attacker could then potentially lure a victim site user into browsing to the poisoned URL, where they would be served malicious content.

It turns out that some origins send back data back from HTTP headers that are not part of the cache key.

To give one example, we might observe origin behavior like:

Because this data is returned, unescaped, from the origin, it can be used in scary ways:

The attacker can now get arbitrary JavaScript to execute on this webpage.

A more subtle attack

There are other versions of the attack that could trick a client into downloading an unwanted but innocuous-looking resource, with harmful consequences.

Many requests that have traveled through another proxy before reaching cache contain the X-Forwarded-Host header. Some origins may rely on this value to serve web pages. For example:

In this case, there’s no way to just block requests with this X-Forwarded-Host header, because it may have a valid purpose. However, we need to ensure that we don’t return this content to any users who didn’t request it!

There are a few ways we could defend against this type of attack. An obvious first answer is to just disable cache. This isn’t a great solution, though, as disabling cache would result in a tremendous amount of traffic on the origin servers, which defeats the purpose of using cache.

Another option is to always include every HTTP header and its value in the cache key. However, there are many headers, and many different innocuous values (e.g. User-Agent). If we always included them in our default cache key, performance would degrade, because different users asking for the same content would get different copies, when they could all be effectively served with one.

Solution

Include “interesting” header values in the cache key:

  • HTTP Scheme
  • HTTP Host
  • Path
  • Query string
  • X-Forwarded-Host header
  • X-Host header
  • X-Forwarded-Scheme header

Web Cache Deception Attack

Web Cache Deception Attack is a type of attack where web app uses cache but it’s not validating properly which allows an attacker to craft cache leakage attacks.

In this scenario, web apps in the background often tend to use a proxy, CDN and other services to use cache functionality in which it reduces the time from the server or simply to reduce latency but not validating properly.

Suppose if there is a website like www.example.com/home.php and you tried an additional extension at the end of this URL like www.example.com/home.php/a.jpg, and if the website has cache functionality, it basically caches the website internal information and stores it into this above endpoint under their cache Directory, Extension can be anything like .css, .jpg, .js anything.

Once the user will visit and their info will be cached, then an attacker will just visit this same endpoint and Boom! user’s personal info can be leaked by visiting source code.

It works against sites that sit behind a reverse proxy and are misconfigured in a particular way. Unfortunately, the definition of "misconfigured" for the purposes of this attack changes depending on how the cache works.

How to

What happens if we access http://www.example.com/home.php/non-existent.css, while web cache for static files is set on the proxy server, disregarding caching headers for this kind of file?

Let's analyze this process:

  1. Browser requests http://www.example.com/home.php/non-existent.css.
  2. Server returns the content of http://www.example.com/home.php, most probably with HTTP caching headers that instruct to not cache this page.
  3. The response goes through the proxy.
  4. The proxy identifies that the file has a css extension.
  5. Under the cache directory, the proxy creates a directory named home.php, and caches the imposter "CSS" file (non-existent.css) inside.

Example

Full size image

An attacker who lures a logged-on user to access http://www.example.com/home.php/logo.png will cause this page – containing the user's personal content – to be cached and thus publicly-accessible. It could get even worse, if the body of the response contains (for some reason) the session identifier, security answers or CSRF tokens. All the attacker has to do now is to access this page on his own and expose this data.

Mitigation

  1. Configure the cache mechanism to cache files only if their HTTP caching headers allow. That will solve the root cause of this issue.
  2. If the cache component provides the option, configure it to cache files by their content type.
  3. Configure the web server so that for pages such as http://www.example.com/home.php/non-existent.css, the web server doesn’t return the content of "home.php" with this URL. Instead, for example, the server should respond with a 404 or 302 response.

Further reading