Web Cache Poisoning
If a server had to send a new response to every single HTTP request separately, this would likely overload the server, resulting in latency issues and a poor user experience, especially during busy periods. Caching is primarily a means of reducing such issues.
The cache sits between the server and the user, where it saves (caches) the responses to particular requests, usually for a fixed amount of time.
If another user then sends an equivalent request, the cache simply serves a copy of the cached response directly to the user, without any interaction from the back-end.
This greatly eases the load on the server by reducing the number of duplicate requests it has to handle.
Types of Caches
Client side Cache: It’s a cache system that’s built into a browser to store files and contents on your computer and are grouped with other files associated with the browser you use.
DNS Cache: DNS cache refers to the temporary storage of information about previous DNS lookups on a machine’s OS or web browser. Keeping a local copy of a DNS lookup allows your OS or browser to quickly retrieve it and thus a website’s URL can be resolved to its corresponding IP much more efficiently.
Web Cache: Data that your device stores when visiting a website for the first time includes images, scripts or other media files such as gifs.
When the cache receives an HTTP request, it first has to determine whether there is a cached response that it can serve directly, or whether it has to forward the request for handling by the back-end server.
Caches identify equivalent requests by comparing a predefined subset of the request’s components, known collectively as the “cache key”. Typically, this would contain the request line and host header.
Components of the request that are not included in the cache key are said to be "unkeyed".
If the cache key of an incoming request matches the key of a previous request, then the cache considers them to be equivalent. As a result, it will serve a copy of the cached response that was generated for the original request.
This applies to all subsequent requests with the matching cache key, until the cached response expires.
Crucially, the other components of the request are ignored altogether by the cache. We’ll explore the impact of this behavior in more detail later.
Web Cache Poisoning
Web cache poisoning is an advanced technique whereby an attacker exploits the behavior of a web server and cache so that a harmful HTTP response is served to other users.
Basically, web cache poisoning involves two phases. First, the attacker must work out how to obtain a response from the back-end server that inadvertently contains some kind of dangerous payload.
Once successful, they need to make sure that their response is cached and subsequently served to the intended victims.
Ways of Cache Poisoning
There are many ways to do Cache Poisoning and are mentioned below
- Unkeyed port
- Unkeyed query string
- Unkeyed query parameters
- Cache parameter cloaking
- Normalized cache keys
- Cache key injection
- Internal cache poisoning
Other ways can also be used to do cache poisoning like http request smuggling and http response splitting.
Impact of a web cache poisoning attack
The impact of web cache poisoning is heavily dependent on two key factors:
- What exactly the attacker can successfully get cached
As the poisoned cache is more a means of distribution than a standalone attack, the impact of web cache poisoning is inextricably linked to how harmful the injected payload is. As with most kinds of attack, web cache poisoning can also be used in combination with other attacks to escalate the potential impact even further.
- The amount of traffic on the affected page
The poisoned response will only be served to users who visit the affected page while the cache is poisoned. As a result, the impact can range from non-existent to massive depending on whether the page is popular or not. If an attacker managed to poison a cached response on the home page of a major website, for example, the attack could affect thousands of users without any subsequent interaction from the attacker.
Note that the duration of a cache entry doesn’t necessarily affect the impact of web cache poisoning. An attack can usually be scripted in such a way that it re-poisons the cache indefinitely.
We’ll use the following methodology to find cache poisoning vulnerabilities:
The first step is to identify unkeyed inputs by guessing header/cookie names, and observing whether they have an effect on the application’s response.
After finding an unkeyed input, the next steps are to assess how much damage you can do with it, then try and get it stored in the cache.
If that fails, you’ll need to gain a better understanding of how the cache works and hunt down a cacheable target page before retrying.
Whether a page gets cached may be based on a variety of factors including the file extension, content-type, route, status code, and response headers.
Cached responses can mask unkeyed inputs, so if you’re trying to manually detect or explore unkeyed inputs, a cache-buster is crucial.
When auditing a live website, accidentally poisoning other visitors is a perpetual hazard.
Prevent web Cache Poisoning Vulnerabilities
The definitive way to prevent web cache poisoning would clearly be to disable caching altogether. While for many websites this might not be a realistic option, in other cases, it might be feasible.
For example, if you only use caching because it was switched on by default when you adopted a CDN, it might be worth evaluating whether the default caching options really do reflect your needs.
Even if you do need to use caching, restricting it to purely static responses is also effective, provided you are sufficiently wary about what you class as “static”.
For instance, make sure that an attacker can’t trick the back-end server into retrieving their malicious version of a static resource instead of the genuine one.
This is also related to a wider point about web security. Most websites now incorporate a variety of third-party technologies into both their development processes and day-to-day operations.
No matter how robust your own internal security posture may be, as soon as you incorporate third-party technology into your environment, you are relying on its developers also being as security-conscious as you are.
On the basis that you are only as secure as your weakest point, it is vital to make sure that you fully understand the security implications of any third-party technology before you integrate it.
Specifically in the context of web cache poisoning, this not only means deciding whether to leave caching switched on by default, but also looking at which headers are supported by your CDN, for example.
Several of the web cache poisoning vulnerabilities discussed above are exposed because an attacker is able to manipulate a series of obscure request headers, many of which are entirely unnecessary for the website’s functionality.
Again, you may be exposing yourself to these kinds of attacks without realizing, purely because you have implemented some technology that supports these unkeyed inputs by default. If a header isn’t needed for the site to work, then it should be disabled.
You should also take the following precautions when implementing caching:
- If you are considering excluding something from the cache key for performance reasons, rewrite the request instead.
- Don’t accept fat
GETrequests. Be aware that some third-party technologies may permit this by default.
- Patch client-side vulnerabilities even if they seem unexploitable. Some of these vulnerabilities might actually be exploitable due to unpredictable quirks in your cache’s behavior. It could be a matter of time before someone finds a quirk, whether it be cache-based or otherwise, that makes this vulnerability exploitable.