Web cache poisoning
Web cache stores HTTP responses to reuse them for identical subsequent requests. The cache decides to store a response based on a "cache key": typically the URL and HTTP method. Poisoning exploits the fact that some request headers influence the response without being part of the cache key. The attacker can thus inject a payload into the response that will be served to other users.
Unkeyed parameters
An "unkeyed input" is a value that influences the response but isn't included in the cache key. Common examples: the X-Forwarded-Host header used by the application to build absolute URLs (e.g., in canonical links or redirects), the X-Forwarded-Scheme header, query parameters ignored by the cache but processed by the application.
Example: poisoning via X-Forwarded-Host
# L'attaquant envoie :
GET / HTTP/1.1
Host: vulnerable.com
X-Forwarded-Host: attacker.com
# Si l'application utilise X-Forwarded-Host pour construire le lien du script :
<script src="https://attacker.com/app.js"></script>
# Et si cette réponse est mise en cache (X-Forwarded-Host n'est pas dans la cache key),
# tous les visiteurs suivants reçoivent la page avec le script de l'attaquant.
Poisoning via HTTP request smuggling
Request smuggling can be combined with cache poisoning to amplify the impact. The attacker smuggles a request that poisons a popular cache entry. The poisoned response (containing for example an XSS payload) is then served to all users requesting the corresponding resource.
Prevention
Prevention acts on multiple levels. Don't use X-Forwarded-* headers to build URLs in the response without adding them to the cache key, or configure the cache to include them. Validate and restrict headers accepted by the proxy or CDN. Disable caching for responses that depend on variable headers. Use Vary to include relevant headers in the cache key.
Include headers in cache key with Vary
# Si la réponse varie selon l'en-tête Accept-Language :
Vary: Accept-Language
# Si l'application utilise X-Forwarded-Host pour construire la réponse :
Vary: X-Forwarded-Host
# (ou mieux : ne pas utiliser X-Forwarded-Host dans la réponse du tout)
Further reading
A question after reading?
Does your application use a CDN or HTTP cache? Send a message.
Or book a 30-minute scoping call directly
Book a call →