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

cache-poisoning-via-url-discrepancies.md (5878B)


      1 ---
      2 title: "Cache Poisoning via URL discrepancies"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Cache Poisoning via URL discrepancies
     14 
     15 This is a summary of the techniques proposed in the post [https://portswigger.net/research/gotta-cache-em-all](https://portswigger.net/research/gotta-cache-em-all) in order to perform cache poisoning attacks **abusing discrepancies between cache proxies and web servers.**<sup>[[1]](#references)</sup>
     16 
     17 > [!TIP]
     18 > The goal is to make the cache classify a request as cacheable while the origin routes the same URL to a dynamic endpoint. If the cache key preserves a suffix or normalized path that the origin discards, the attacker may store a personalized response, an XSS/redirect response, or a reference to attacker-controlled JavaScript under a reusable key.
     19 
     20 ## Delimiters
     21 
     22 **URL delimiters** vary by framework and server, impacting how requests are routed and responses are handled.<sup>[[1]](#references)</sup> Some common origin delimiters are:
     23 
     24 - **Semicolon**: Used in Spring for matrix variables (e.g. `/hello;var=a/world;var1=b;var2=c` → `/hello/world`).
     25 - **Dot**: Can select a response format in Ruby on Rails (e.g. `/MyAccount.css` may route to `/MyAccount` with a CSS format).
     26 - **Null Byte**: Truncates paths in OpenLiteSpeed (e.g. `/MyAccount%00aaa` → `/MyAccount`).
     27 - **Newline Byte**: Separates URL components in Nginx (e.g. `/users/MyAccount%0aaaa` → `/account/MyAccount`).
     28 
     29 Other specific delimiters might be found following this process:
     30 
     31 - **Step 1**: Identify non-cacheable requests and use them to monitor how URLs with potential delimiters are handled.
     32 - **Step 2**: Append random suffixes to paths and compare the server's response to determine if a character functions as a delimiter.
     33 - **Step 3**: Introduce potential delimiters before the random suffix to see if the response changes, indicating delimiter usage.<sup>[[1]](#references)</sup>
     34 
     35 ## Normalization & Encodings
     36 
     37 - **Purpose**: URL parsers in both cache and origin servers normalize URLs to extract paths for endpoint mapping and cache keys.
     38 - **Process**: Identifies path delimiters, extracts and normalizes the path by decoding characters and removing dot-segments.
     39 
     40 ### **Encodings**
     41 
     42 Different HTTP servers and proxies like Nginx, Node, and CloudFront decode delimiters differently, leading to inconsistencies across CDNs and origin servers that could be exploited. For example, if the web server perform this transformation `/myAccount%3Fparam` → `/myAccount?param` but the cache server keeps as key the path `/myAccount%3Fparam`, there is an inconsistency.<sup>[[1]](#references)</sup>
     43 
     44 A way to check for these inconsistencies is to send requests URL encoding different chars after loading the path without any encoding and check if the encoded path response came from the cached response.<sup>[[1]](#references)</sup>
     45 
     46 ### Dot segment
     47 
     48 Dot-segment normalization is another source of discrepancies. For `/static/../home/index` or `/aaa..\home/index`, one component may key the literal path while another resolves dot segments or backslashes. Compare a cache-busted baseline with the normalized and non-normalized variants, and use only non-sensitive test accounts because a successful cache-deception probe may publish a response.<sup>[[1]](#references)</sup>
     49 
     50 ## Static Resources
     51 
     52 Many caches apply default or configured rules that make apparently static resources cacheable.<sup>[[1]](#references)</sup> Common classifiers include:
     53 
     54 - **The extension**: By default, Cloudflare considers a documented list of extensions cacheable and does not cache HTML or JSON merely because of MIME type. Actual storage still depends on method, response code, cache-control, size, plan, and cache rules; “cacheable by extension” does not mean a response is always cached.<sup>[[2]](#references)</sup> The current default list includes: 7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, and xlsx.
     55   - A delimiter plus a static extension may store a dynamic response: the cache keys `/home$image.png`, while the origin treats `$image.png` as a delimiter/suffix and routes to `/home`.
     56 - **Well-known static directories**: Custom cache rules often classify paths such as `/static`, `/assets`, `/wp-content`, `/media`, `/templates`, `/public`, or `/shared` as static. These are conventions, not universal cache behavior.
     57   - A delimiter, static directory, and encoded traversal can produce the same mismatch; for example, one component may key `/home/..%2fstatic/something` as `/static/something` while the origin responds with `/home`.
     58   - **Static dirs + dots**: A request to `/static/..%2Fhome` or to `/static/..%5Chome` might be cached as is but the response might be `/home`
     59 - **Static files:** Cache rules may special-case files such as `/robots.txt`, `/favicon.ico`, or `/index.html`. A path such as `/home/..%2Frobots.txt` may therefore be keyed as `/robots.txt` while the origin responds with `/home`.<sup>[[1]](#references)</sup>
     60 
     61 ## References
     62 
     63 - [1] [Gotta cache 'em all: bending the rules of web cache exploitation](https://portswigger.net/research/gotta-cache-em-all)
     64 - [2] [Cloudflare — Default cache behavior and cached extensions](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/)