Umgehung der SMS-Zwei-Faktor-Authentifizierung per Brute-Force: Ein Pentest-Bericht einer Bank
Während eines autorisierten Black-Box-Pentests einer großen Bankinfrastruktur (4.000 Hosts, 4.500 Nutzer) wurde im persönlichen Kundenportal für Finanzanträge eine kritische Umgehung der SMS-basierten Zwei-Faktor-Authentifizierung (2FA) entdeckt. Ein Angreifer mit Zugriff auf die Telefonnummer des Opfers konnte einen Brute-Force-Angriff auf einen 4-stelligen Code vollständig automatisieren – ohne jegliche Ratenbegrenzung – und erhielt so vollen Zugriff auf Passdaten, Antragshistorien und Werkzeuge für betrügerische Transaktionen.
Dieser Zugriff ermöglichte Kreditanträge, Genehmigungen für Projektfinanzierungen und Zahlungsbestätigungen über den Kundenservice – ohne zusätzliche Verifizierung. Bei 10.000 möglichen Kombinationen konnte der Code in Sekunden geknackt werden.
Analyse der API- und Authentifizierungslogik
Der Anmeldeprozess stützte sich auf zwei Endpunkte:
- SMS-Anforderung:
POSTgibt"repeat":180zurück und blockiert Wiederholungen für 3 Minuten. - Code-Verifizierung:
POST /api/*****/loginmit dem Body"{code":"0548","phone":"+7(111)222-22-22"}.
Ein falscher Code liefert HTTP 400 mit "Telefonnummer oder Code ist falsch." Ein korrekter Code liefert HTTP 200 mit Session-Cookies (JSESSIONID, PHPSESSID). Es gab keine Versuchszähler, CAPTCHA, IP- oder Session-Blockierungen. Jede Anfrage wurde unabhängig verarbeitet.
POST /api/*****/login HTTP/1.1
Host: ****
Content-Type: application/json
{"code":"0548","phone":"+7(111) 222-22-22"}
Implementierung des Exploits in JavaScript
Der PoC nutzte den Browser-Session-Kontext, um CORS- und SameSite-Beschränkungen zu umgehen. Die Kernschleife führte paralleles Brute-Forcing über 20 Threads durch:
await fetch('https://roga_and_copyta/*****/api/*****/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({code: codeStr, phone: phone})
});
for (let i = 0; i < 20; i++) {
turboThread(i, start, end); // Code-Bereich
}
if (response.status === 200) {
foundCode = codeStr;
// Feld automatisch ausfüllen
}
Der Erfolg wurde durch eine 200-Statusantwort bestimmt. Ein ähnliches Skript funktionierte in Python. Angriffszeit: 35 Sekunden für 10.000 Anfragen.
Klassifizierung der Schwachstelle und Ursachen
Die Schwachstelle entspricht CWE-307 (Unzureichende Einschränkung übermäßiger Authentifizierungsversuche). CVSS 3.1-Score: 9,1 (Kritisch) – Netzwerk, geringe Komplexität, keine Privilegien, keine Benutzerinteraktion.
Kritische Designfehler:
- Benutzerfreundlichkeit über Sicherheit: Keine Ratenbegrenzung, um Beschwerden über Tippfehler zu vermeiden.
- Automatisierungs-Blindstelle: 4-stellige Codes sind für Menschen schwer, aber für Skripte trivial.
- Keine Brute-Force-Tests: Sicherheitsannahmen wurden nie validiert.
Empfehlungen zur Behebung
Für eine mehrschichtige Verteidigung implementieren:
- Versuchsgrenzen: 3–5 Versuche pro Code, mit erneutem SMS-Versand.
- CAPTCHA nach 2–3 fehlgeschlagenen Versuchen.
- 6-stellige Codes (1 Million Kombinationen; Brute-Force dauert Stunden).
- Anomalie-Überwachung: Anfragehäufigkeit, IP-Reputationsprüfungen.
- Ratenbegrenzung nach Telefonnummer und Session.
// Beispiel für Backend-Ratenbegrenzung (Pseudocode)
if (attempts[phone] > 5) {
invalidateCode(phone);
requireCaptcha();
}
Wichtige Erkenntnisse
- Das Umgehen der 2FA gewährt vollen Zugriff auf das Konto: Passdetails, Anträge, Bankdaten, Zahlungsbestätigungen.
- Ein 4-stelliger Code ohne Grenzen = 10.000 Kombinationen, in 35 Sekunden geknackt.
- CWE-307 (CVSS 9,1): Fehlender Schutz vor automatisierten Brute-Force-Angriffen.
- Empfehlung: Grenzen + CAPTCHA + 6-stellige Codes + Echtzeit-Überwachung durchsetzen.
- Die Schwachstelle wurde während des Pentests vor einer Ausnutzung identifiziert; alle Probleme wurden gepatcht.
— Editorial Team
Noch keine Kommentare.