Web Cache Poisoning - Not only a Theoretical Attack

Web Cache Poisoning

Not only a Theoretical Attack

Ralph Meier
by Ralph Meier
on May 12, 2022
time to read: 8 minutes

Keypoints

How to identify Web Cache Poisoning Vulnerabilities

  • Various cache mechanisms are used to reduce the latency of a response on the Internet
  • Cache keys can be configured individually, but by default consist of a combination of host and query string
  • Procedure for discovering web cache poisoning vulnerabilities
  • Increase resistance to Web cache poisoning attacks

Web cache poisoning is an attack on the cache used by the web server or web application, whereby its behaviour can be manipulated and thus foreign visitors to the website can be attacked. Web cache poisoning is considered an advanced technique and essentially consists of searching for a suitable input, which is reflected by the server, and a working payload.

There are a variety of different types of caches, but most of them have the same main goals – less network traffic, thus shorter response time and less load on the web server. Caches are located between the user and the web page. In a cache, requests for resources and their response, or a copy of the resources (images, texts and other components) are stored for a set time.

Different Caches

The browser cache is located locally on the user’s computer, more precisely in their browser. Thus, another browser on the same computer has no access to the stored contents of the first browser cache. The browser cache belongs to the so-called private caches, as third parties have no access to it.

Proxy servers can also have a cache, but this is not bound to the user; all connections that go through the same proxy server can access it. However, this does not necessarily have to be all visitors to website X.

In addition, the web server can have its own caching mechanisms, for example via a framework such as Drupal, or the used Content Delivery Network (CDN) has its own caching. In some cases, specific products such as Varnish are also used.

There are other types of caches, but the focus of this article is on caching mechanisms that are used by all website visitors, so-called shared caches.

Cache-Control Header

The Cache-Control Header is an HTTP header that can be used in requests and responses to control caching. This header determines whether, who and for how long a request or response may be cached. Who means various cache parties such as the browser, a proxy server, CDNs and others.

With max-age the maximum cache duration in seconds can be set Cache-Control: max-age=604800. The cache duration starts from the time when the response was generated by the server.

Requests or responses that contain sensitive content should not be cached for security reasons; Cache-Conrol: no-store should be used for this.

Further information on the Cache-Control-Header is available in the Mozilla documentation.

Cache Keys

So that the cache does not have to compare the complete request with the currently stored request, so-called cache keys are used. Cache keys normally consist of the HTTP query and the host name, but this can also be configured differently. If there is a match, the stored copy of the response is transmitted directly to the request originator. This happens as long as the cached resource is valid. Possible cache key of this article: "/en/?labs.20220512" + "www.scip.ch"

Unkeyed

Components of the request that are not part of the cache key are called unkeyed inputs. Unkeyed inputs can be request headers, cookies, in rare cases also parts of the query string or parts of the request body (Fat GET requests). These unkeyed inputs can lead to problems or enable a web cache poisoning vulnerability.

Web Cache Poisoning Example

In the following example, the X-Forwarded-Host header is used to generate an Open Graph URL within a meta tag. In this case, changing the X-Forwarded-Host header could determine the domain and load a different image. Since this is cached, all other visitors with the same query string within the validity period of the cache will also receive this image.

GET /en?param=test HTTP/1.1
Host: www.example.com
X-Forwarded-Host: evil

HTTP/1.1 200 OK
...
<meta property="og:image" content="https://evil/images/cat.png" />

Instead of a domain, JavaScript can also be embedded, which leads to a cross-site scripting attack:

GET /en?param=test2 HTTP/1.1
Host: www.example.com
X-Forwarded-Host: a."><script>alert(1)</script>

HTTP/1.1 200 OK
...
<meta property="og:image" content="https://a."><script>alert(1)</script>" />

The examples are inspired by the paper Practical Web Cache Poisoning, which describes many different types of web cache poisoning attacks. Web cache poisoning payloads can also include open redirects or DOM-XSS attacks, as well as other attacks.

Steps to a Web Cache Poisoning Vulnerability

First, start by looking for unkeyed inputs and what their effect is, i.e. how they are returned in the server response. This evaluation can either be done manually with known request headers and other frequently affected unkeyed inputs or with the help of Param Miner, an open source burp plugin that greatly simplifies the search for an unkeyed input.

When a promising unkeyed input has been found, the search begins for a payload that is functionally returned by the web server in the corresponding response.

After the payload has been determined, the response with the reflected payload is cached in a final step so that it is delivered to the desired third-party visitors via the cache used.

When testing an application for a web cache poisoning vulnerability, a cache buster should be used. This is a random URL parameter that prevents normal users from being affected by testing. www.example.com/en?RandomCacheBuster=123

Countermeasures

The simplest and at the same time most drastic countermeasure is to do without caching completely. This works for small websites that have little network traffic and a web server with sufficient performance. In this case, it may be that web frameworks are used that have caching by default, but since it is not needed, it can be deactivated and thus the attack surface can be reduced.

If caching cannot be dispensed with completely, only static resources should be cached. This prevents web cache poisoning, since no user input is processed when requests are made to static resources, they are also not susceptible to web cache poisoning attacks.

If the caching of static content is not sufficient, it can be extended to dynamic content, but should not process input from request headers, cookies or reflect unkeyed inputs in the response. It should be noted that some frameworks have their own request headers, which could also be vulnerable. The possibility of web cache poisoning due to a configuration error cannot be ruled out.

There is also the option of including unkeyed request headers in the cache key, which makes the cache key longer. Because the cache key now contains additional components, there may occasionally be several entries in the cache, but the possibility of a successful web cache poisoning attack is reduced. The contents of request headers should not be used if they are not part of the cache key. In addition, HTTP headers should never be returned directly to users for cached resources.

GET requests with body (Fat GET), which result in changes to the server response, should be avoided.

An additional security measure would be to test the web application by using the Burp plugin Param Miner and to check detected HTTP headers or other unkeyed inputs more closely.

Conclusion

Web cache poisoning was long considered a theoretical attack, but Bug Bounty platforms have shown that this combination of a cache attack and another vulnerability is now also quite practical. Therefore, cache configurations should be well thought out and not left at the default configuration. Cache mechanisms supplied with the framework should be deactivated if there is no need for caching. If you would like to find a web cache poisoning vulnerability yourself in a training environment, we recommend Portswigger Labs.

About the Author

Ralph Meier

Ralph Meier completed an apprenticeship as an application developer, with a focus on web development with Java, at a major Swiss bank and then completed a Bachelor of Science in Computer Science UAS Zurich at the ZHAW School of Engineering. His primary task is doing security-related analysis of web applications and services. (ORCID 0000-0002-3997-8482)

Links

You want to test the security of your firewall?

Our experts will get in contact with you!

×
Dynamic Analysis of Android Apps

Dynamic Analysis of Android Apps

Ralph Meier

Burp Bambdas & BChecks

Burp Bambdas & BChecks

Ralph Meier

Disk Cloning

Disk Cloning

Ralph Meier

The BIOS

The BIOS

Ralph Meier

You want more?

Further articles available here

You need support in such a project?

Our experts will get in contact with you!

You want more?

Further articles available here