Contournement de l'authentification à deux facteurs par SMS via force brute : Analyse d'un test d'intrusion bancaire
Lors d'un test d'intrusion en boîte noire autorisé sur l'infrastructure d'une grande banque (4 000 hôtes, 4 500 utilisateurs), une vulnérabilité critique permettant de contourner l'authentification à deux facteurs (2FA) par SMS a été découverte dans le portail de compte personnel pour les demandes financières. Un attaquant ayant accès au numéro de téléphone de la victime pouvait automatiser entièrement une attaque par force brute sur un code à 4 chiffres sans aucune limitation de débit, obtenant ainsi un accès complet aux données de passeport, aux historiques de demandes et aux outils de transactions frauduleuses.
Cet accès permettait de soumettre des demandes de prêt, d'approuver des financements de projets et de confirmer des paiements via le support client — sans vérification supplémentaire. Avec 10 000 combinaisons possibles, le code pouvait être craqué en quelques secondes.
Analyse de l'API et de la logique d'authentification
Le processus de connexion reposait sur deux points d'accès :
- Demande de SMS :
POSTrenvoie"repeat":180, bloquant les nouvelles tentatives pendant 3 minutes. - Vérification du code :
POST /api/*****/loginavec le corps"{code":"0548","phone":"+7(111)222-22-22"}.
Un code incorrect renvoie HTTP 400 avec "Numéro de téléphone ou code incorrect." Un code correct renvoie HTTP 200 avec des cookies de session (JSESSIONID, PHPSESSID). Aucun compteur de tentatives, CAPTCHA, blocage d'IP ou de session n'était en place. Chaque requête était traitée indépendamment.
POST /api/*****/login HTTP/1.1
Host: ****
Content-Type: application/json
{"code":"0548","phone":"+7(111) 222-22-22"}
Implémentation de l'exploit en JavaScript
La preuve de concept exploitait le contexte de session du navigateur pour contourner les restrictions CORS et SameSite. La boucle principale effectuait une attaque par force brute parallèle sur 20 threads :
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); // Plage de codes
}
if (response.status === 200) {
foundCode = codeStr;
// Remplissage automatique du champ
}
Le succès était déterminé par une réponse de statut 200. Un script similaire fonctionnait en Python. Temps d'attaque : 35 secondes pour 10 000 requêtes.
Classification de la vulnérabilité et causes profondes
Cette faille correspond à CWE-307 (Restriction incorrecte des tentatives d'authentification excessives). Score CVSS 3.1 : 9,1 (Critique) — Réseau, faible complexité, aucun privilège, aucune interaction utilisateur.
Échecs de conception critiques :
- Utilisabilité au détriment de la sécurité : Aucune limitation de débit pour éviter les plaintes sur les fautes de frappe.
- Angle mort de l'automatisation : 4 chiffres sont difficiles pour les humains mais triviaux pour les scripts.
- Aucun test de force brute : Les hypothèses de sécurité n'ont jamais été validées.
Recommandations de correction
Pour une défense en couches, implémentez :
- Limites de tentatives : 3 à 5 essais par code, avec renvoi de SMS.
- CAPTCHA après 2 à 3 tentatives échouées.
- Codes à 6 chiffres (1 million de combinaisons ; la force brute prend des heures).
- Surveillance des anomalies : Fréquence des requêtes, vérifications de réputation IP.
- Limitation de débit par numéro de téléphone et session.
// Exemple de limitation de débit côté serveur (pseudocode)
if (attempts[phone] > 5) {
invalidateCode(phone);
requireCaptcha();
}
Points clés à retenir
- Contourner la 2FA donne un accès complet au compte : détails du passeport, demandes, coordonnées bancaires, confirmations de paiement.
- Un code à 4 chiffres sans limites = 10 000 combinaisons, craqué en 35 secondes.
- CWE-307 (CVSS 9,1) : absence de protection contre les attaques par force brute automatisées.
- Recommandation : appliquer des limites + CAPTCHA + codes à 6 chiffres + surveillance en temps réel.
- La vulnérabilité a été identifiée lors d'un test d'intrusion avant exploitation ; tous les problèmes ont été corrigés.
— Editorial Team
Aucun commentaire pour le moment.