diff --git a/src/pentesting-web/cache-deception/README.md b/src/pentesting-web/cache-deception/README.md index 24b149b9c..506efe1f3 100644 --- a/src/pentesting-web/cache-deception/README.md +++ b/src/pentesting-web/cache-deception/README.md @@ -294,6 +294,89 @@ Note that the **cache proxy** should be **configured** to **cache** files **base Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception). +### 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. + +High level idea: + +- A sensitive API endpoint requires a custom auth header and is correctly marked as non-cacheable by origin. +- Appending a static-looking suffix (for example, .css) makes the CDN treat the path as a static asset and cache the response, often without varying on sensitive headers. +- The SPA contains CSPT: it concatenates a user-controlled path segment into the API URL while attaching the victim’s auth header (for example, X-Auth-Token). By injecting ../.. traversal, the authenticated fetch is redirected to the cacheable path variant (…/v1/token.css), causing the CDN to cache the victim’s token JSON under a public key. +- Anyone can then GET that same cache key without authentication and retrieve the victim’s token. + +Example + +- Sensitive endpoint (non-cacheable at origin): + +``` +GET /v1/token HTTP/1.1 +Host: api.example.com +X-Auth-Token: +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..."} +``` + +- Static-looking suffix flips CDN to cacheable: + +``` +GET /v1/token.css HTTP/1.1 +Host: api.example.com +X-Auth-Token: +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 attaches auth header and allows traversal: + +```js +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 } +}); +``` + +- Exploit chain: + 1. Lure victim to a URL that injects dot-segments into the SPA path parameter, e.g.: + - [https://example.com/user?userId=../../../v1/token.css](https://example.com/user?userId=../../../v1/token.css) + 2. The SPA issues an authenticated fetch to: + - [https://api.example.com/v1/users/info/../../../v1/token.css](https://api.example.com/v1/users/info/../../../v1/token.css) + 3. Browser normalization resolves it to: + - [https://api.example.com/v1/token.css](https://api.example.com/v1/token.css) + 4. The CDN treats .css as a static asset and caches the JSON with Cache-Control: public, max-age=... + 5. Public retrieval: anyone can then GET https://api.example.com/v1/token.css and obtain the cached token JSON. + +Preconditions + +- SPA performs authenticated fetch/XHR to the same API origin (or cross-origin with working CORS) and attaches sensitive headers or bearer tokens. +- Edge/CDN applies extension-based caching for static-looking paths (e.g., *.css, *.js, images) and does not vary the cache key on the sensitive header. +- Origin for the base endpoint is non-cacheable (correct), but the extension-suffixed variant is allowed or not blocked by edge rules. + +Validation checklist + +- Identify sensitive dynamic endpoints and try suffixes like .css, .js, .jpg, .json. Look for Cache-Control: public/max-age and X-Cache: Hit (or equivalent, e.g., CF-Cache-Status) while content remains JSON. +- Locate client code that concatenates user-controlled input into API paths while attaching auth headers. Inject ../ sequences to redirect the authenticated request to your target endpoint. +- Confirm the authenticated header is present on the retargeted request (e.g., in a proxy or via server-side logs) and that the CDN caches the response under the traversed path. +- From a fresh context (no auth), request the same path and confirm the secret JSON is served from cache. + + ## Automatic Tools - [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques. @@ -309,6 +392,11 @@ Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request S - [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/) - [Burp Proxy Match & Replace](https://portswigger.net/burp/documentation/desktop/tools/proxy/match-and-replace) - [watchTowr Labs – Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/) +- [Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover](https://zere.es/posts/cache-deception-cspt-account-takeover/) +- [CSPT overview by Matan Berson](https://matanber.com/blog/cspt-levels/) +- [CSPT presentation by Maxence Schmitt](https://www.youtube.com/watch?v=O1ZN_OCfNzg) +- [PortSwigger: Web Cache Deception](https://portswigger.net/web-security/web-cache-deception) + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/client-side-path-traversal.md b/src/pentesting-web/client-side-path-traversal.md index 55b1c475e..19d815776 100644 --- a/src/pentesting-web/client-side-path-traversal.md +++ b/src/pentesting-web/client-side-path-traversal.md @@ -13,6 +13,29 @@ A client side path traversal occurs when you can **manipulate the path of a URL* - Check this [**CSPT playground**](https://github.com/doyensec/CSPTPlayground) to try the technique. - Check [**this tutorial**](https://blog.doyensec.com/2024/12/03/cspt-with-eval-villain.html) on how to use the browser extension in the playground. +## CSPT-assisted web cache poisoning/deception + +CSPT can be chained with extension-based CDN caching to exfiltrate sensitive JSON leaked by authenticated API calls: + +- A frontend concatenates user-controlled input into an API path and attaches authentication headers in fetch/XHR. +- By injecting dot-segments (../) you can retarget the authenticated request to a different endpoint on the same origin. +- If that endpoint (or a path variant with a static-looking suffix like .css) is cached by the CDN without varying on auth headers, the victim’s authenticated response can be stored under a public cache key and retrieved by anyone. + +Quick recipe: + +1) Find SPA code building API URLs from path parameters while sending auth headers. +2) Identify sensitive endpoints and test static suffixes (.css, .js, .jpg, .json) to see if the CDN flips to Cache-Control: public/max-age and X-Cache: Hit while returning JSON. +3) Lure the victim to a URL that injects traversal into the SPA parameter so the authenticated fetch hits the cacheable path variant (for example, ../../../v1/token.css). +4) Read back the same URL anonymously to obtain the cached secret (token → ATO). + +See details and mitigations in the Cache Deception page: [Cache Poisoning and Cache Deception](cache-deception/). + +## References + +- [Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover](https://zere.es/posts/cache-deception-cspt-account-takeover/) +- [CSPT overview by Matan Berson](https://matanber.com/blog/cspt-levels/) +- [PortSwigger: Web Cache Deception](https://portswigger.net/web-security/web-cache-deception) + {{#include ../banners/hacktricks-training.md}}