Aller au contenu

Analyse télémétrique du password spraying & Brute-force

Malgré la promotion croissante des architectures sans mot de passe (passwordless), les mots de passe demeurent le facteur d’authentification principal pour l’immense majorité des entreprises sous Microsoft 365. Si les attaques par force brute traditionnelles (tester rapidement des milliers de mots de passe sur une même cible) sont neutralisées par les mécanismes d’Entra Smart Lockout, le Password Spraying reste l’un des vecteurs d’accès initial les plus dévastateurs et répandus.

Dans une attaque par password spraying, l’attaquant inverse la logique de force brute : au lieu de tester de nombreux mots de passe contre un compte unique, il teste un mot de passe unique et probable (ex. Automne2026!, Entreprise123#) contre des milliers d’identités du tenant sur une période étendue. En répartissant les requêtes à travers des proxys résidentiels rotatifs et en ciblant les protocoles d’authentification héritée, les cybercriminels échappent aux seuils d’alerte et neutralisent les défenses périmétriques.

Ce guide propose une dissection technique et forensique du password spraying sous Entra ID, analyse les méthodes d’énumération préalable d’utilisateurs, détaille la signification exacte des codes d’erreur de connexion et fournit des requêtes de détection KQL de niveau production.


1. Mécanismes d’attaque : force Brute vs password spraying distribué

Section intitulée « 1. Mécanismes d’attaque : force Brute vs password spraying distribué »
graph TD
subgraph "Force Brute Verticale (Bloquée par Smart Lockout)"
ATT1[Attaquant] -->|1 000 Mots de passe / 1 Utilisateur| USER_A[alice@target.com]
USER_A --> LOCKOUT[Smart Lockout Déclenché<br/>ResultType : 50053<br/>IP Bloquée / Compte Verrouillé]
end
subgraph "Password Spraying Horizontal (Furtif)"
ATT2[Réseau de Proxys Résidentiels] -->|Mot de passe unique : Printemps2026!| POOL{Annuaire Utilisateurs}
POOL -->|Tentative 1 / IP 1| U1[user1@target.com]
POOL -->|Tentative 1 / IP 2| U2[user2@target.com]
POOL -->|Tentative 1 / IP 3| U3[user3@target.com]
POOL -->|Tentative 1 / IP N| UN[userN@target.com]
U1 & U2 & U3 & UN --> IDP[Entra ID Security Token Service]
IDP -->|Seuils Non Dépassés| STEALTH[Contourne le Verrouillage et le Blocage d'IP]
end

Pourquoi le password spraying échappe aux détections :

Section intitulée « Pourquoi le password spraying échappe aux détections : »
  1. Basse fréquence par compte : tester un mot de passe toutes les 2 à 4 heures par identité n’atteint jamais les seuils d’Entra ID Smart Lockout (qui verrouille généralement après 10 échecs consécutifs sur une fenêtre glissante).
  2. Rotation des adresses IP résidentielles : les outils d’attaque modernes acheminent chaque requête via des réseaux de proxys résidentiels commerciaux, garantissant qu’aucune adresse IP source n’émet plus de 1 ou 2 tentatives.
  3. Ciblage des protocoles hérités (legacy auth) : les attaquants dirigent leurs attaques vers les points d’entrée de messagerie anciens (IMAP4, POP3, ActiveSync, SMTP AUTH) qui ne supportent pas les invites MFA interactives ni les contrôles de conformité de terminal de l’Accès Conditionnel.

2. Reconnaissance préalable : l’API d’énumération GetCredentialType

Section intitulée « 2. Reconnaissance préalable : l’API d’énumération GetCredentialType »

Avant de déclencher une campagne de spray, les cybercriminels filtrent leur dictionnaire d’adresses afin d’exclure les identifiants inexistants, évitant ainsi de générer du bruit inutile ou des codes d’erreur d’utilisateur inconnu.

2.1 sondage du Point de terminaison des métadonnées

Section intitulée « 2.1 sondage du Point de terminaison des métadonnées »

Entra ID expose une API publique et non authentifiée, exploitée par le portail officiel de connexion Microsoft pour déterminer la personnalisation graphique du tenant, le mode de fédération et les options d’authentification :

POST /common/GetCredentialType?mkt=fr-FR HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/json
{
"username": "victime@target.com",
"isOtherIdpSupported": true,
"checkPhones": false,
"isRemoteNGCSupported": true,
"isCookieBannerShown": false,
"isFidoSupported": true,
"country": "FR",
"forceotclogin": false,
"isExternalFederationDisallowed": false,
"isRemoteConnectSupported": false,
"federationFlags": 0,
"isSignup": false,
"flowToken": "..."
}

2.2 interprétation forensique du paramètre IfExistsResult

Section intitulée « 2.2 interprétation forensique du paramètre IfExistsResult »

La réponse JSON contient un champ entier, IfExistsResult, qui révèle l’existence réelle du compte sans consigner la moindre trace dans les SigninLogs :

Valeur d’IfExistsResultÉtat du Compte dans Entra IDConséquence Forensique
0L’utilisateur existe (compte valide)Le compte est actif dans l’annuaire du tenant. Ajouté à la liste de spray de l’attaquant.
1L’utilisateur n’existe pasL’identifiant est erroné. Écarté par l’attaquant pour ne pas créer d’anomalies.
5Requête régulée (throttled)Le STS Microsoft a temporairement freiné l’adresse IP de l’attaquant.
6Domaine fédéréLe tenant délègue l’authentification à un STS local (ADFS/PingFederate).

3. Décodage télémétrique des codes d’erreur entra ID

Section intitulée « 3. Décodage télémétrique des codes d’erreur entra ID »

Lors d’une campagne de password spraying, chaque tentative est consignée dans la table SigninLogs. La maîtrise des codes ResultType permet à l’analyste de distinguer un mot de passe erroné anodin d’une découverte de mot de passe valide par l’attaquant :

graph TD
ATT[Tentative de Spray Reçue par le STS] --> EVAL{Vérification des Identifiants}
EVAL -->|Mot de Passe Incorrect| RT_50126[ResultType : 50126<br/>Identifiant ou mot de passe invalide]
EVAL -->|Compte Verrouillé| RT_50053[ResultType : 50053<br/>Smart Lockout déclenché]
EVAL -->|Compte Inexistant| RT_50056[ResultType : 50056<br/>Utilisateur absent du tenant]
EVAL -->|Mot de Passe Correct !| MFA_CHECK{Le Compte Exige-t-il le MFA ?}
MFA_CHECK -->|Oui| RT_50076[ResultType : 50076<br/>SIGNAL FORENSIQUE CRITIQUE :<br/>Mot de passe valide, redirigé vers MFA !]
MFA_CHECK -->|Non / Protocole Hérité| RT_0[ResultType : 0<br/>SUCCÈS : Prise de contrôle du compte]

3.1 codes d’erreur fondamentaux pour l’analyse DFIR

Section intitulée « 3.1 codes d’erreur fondamentaux pour l’analyse DFIR »
ResultTypeDescription de l’ErreurSignification en Investigation
0SuccèsAuthentification réussie. Si précédé d’échecs 50126, prouve la réussite d’une tentative de spray.
50126Identifiant OU mot de passe invalideÉchec classique d’authentification. Trace de base du password spraying lorsqu’elle est distribuée sur de multiples comptes.
50053Compte verrouillé (smart lockout)Le seuil d’échecs a été dépassé. Indique un spray agressif ou simultané.
50056L’utilisateur n’existe pasRévèle une attaque sans énumération préalable (utilisation d’un dictionnaire non qualifié).
50076Redirigé vers le MFAVALEUR FORENSIQUE MAXIMALE. Prouve que l’attaquant a trouvé le bon mot de passe, mais a été arrêté par l’exigence MFA. Endiguement immédiat requis !
50079Inscription MFA requiseL’attaquant a trouvé le mot de passe valide d’un compte sans MFA enrôlé ; il peut enrôler sa propre méthode !
50074Échec d’authentification forteLe challenge MFA a été émis (push/SMS) mais refusé ou ignoré par l’utilisateur légitime.
53003Bloqué par l’accès conditionnelLes identifiants étaient valides, mais une règle (pays, équipement non conforme) a bloqué l’accès.

4.1 détection du password spraying distribué multi-comptes

Section intitulée « 4.1 détection du password spraying distribué multi-comptes »

Identifier les cas où de multiples comptes distincts subissent des échecs d’authentification (50126) sur une fenêtre de 2 heures depuis différentes adresses IP partageant des caractéristiques communes :

let ThresholdFailedUsers = 15; // Nombre minimal d'utilisateurs distincts ciblés
let TimeWindow = 2h;
SigninLogs
| where TimeGenerated >= ago(24h)
| where ResultType in (50126, 50053) // Mot de passe invalide ou compte verrouillé
| summarize
FailedAttemptCount = count(),
TargetedUsers = make_set(UserPrincipalName),
TargetedUserCount = dcount(UserPrincipalName),
IPAddresses = make_set(IPAddress),
IPCount = dcount(IPAddress),
Locations = make_set(Location),
AppNames = make_set(AppDisplayName),
UserAgents = make_set(UserAgent)
by bin(TimeGenerated, TimeWindow), ClientAppUsed
| where TargetedUserCount >= ThresholdFailedUsers
| project TimeGenerated, ClientAppUsed, TargetedUserCount, FailedAttemptCount, IPCount, AppNames, UserAgents, TargetedUsers, IPAddresses
| sort by TargetedUserCount desc

4.2 détection de la découverte d’un mot de passe valide (50126 suivi de 50076 OU 0)

Section intitulée « 4.2 détection de la découverte d’un mot de passe valide (50126 suivi de 50076 OU 0) »

Repérer spécifiquement les comptes pour lesquels un attaquant a réussi à identifier le mot de passe valide au cours d’une campagne :

let SprayedUsers = SigninLogs
| where TimeGenerated >= ago(24h)
| where ResultType == 50126
| distinct UserPrincipalName;
SigninLogs
| where TimeGenerated >= ago(24h)
| where UserPrincipalName in (SprayedUsers)
| where ResultType in (0, 50076, 50079) // Succès ou mot de passe valide exigeant le MFA
| project TimeGenerated, UserPrincipalName, IPAddress, Location, ResultType, ResultDescription, AppDisplayName, ClientAppUsed, UserAgent
| sort by TimeGenerated asc

4.3 chasse au spraying sur protocoles d’authentification héritée

Section intitulée « 4.3 chasse au spraying sur protocoles d’authentification héritée »

Repérer les attaques ciblant les protocoles anciens qui court-circuitent les mécanismes modernes d’authentification :

SigninLogs
| where TimeGenerated >= ago(7d)
| where ClientAppUsed in ("IMAP4", "POP3", "SMTP", "Exchange ActiveSync", "MAPI over HTTP", "Autodiscover")
| where ResultType in (50126, 50053, 0)
| summarize
Attempts = count(),
SuccessfulLogins = countif(ResultType == 0),
FailedLogins = countif(ResultType != 0),
DistinctUsers = dcount(UserPrincipalName),
TargetedAccounts = make_set(UserPrincipalName)
by IPAddress, Location, AutonomousSystemNumber, ClientAppUsed, bin(TimeGenerated, 1h)
| where DistinctUsers >= 5
| sort by DistinctUsers desc

5. Stratégie de durcissement architectural et neutralisation

Section intitulée « 5. Stratégie de durcissement architectural et neutralisation »

Pour neutraliser durablement les attaques par password spraying, les équipes de sécurité doivent combiner plusieurs couches défensives :

graph TD
DEF[Architecture Anti-Password Spray] --> L1[1. Bloquer l'Authentification Héritée<br/>Accès Conditionnel : Applications clientes = Autres / ActiveSync]
DEF --> L2[2. Durcir Entra Smart Lockout<br/>Seuil de verrouillage = 5 / Durée = 15 min / Analyse comportementale IP]
DEF --> L3[3. Imposer un MFA Résistant au Phishing<br/>Exiger FIDO2 / Windows Hello via Authentication Strengths]
DEF --> L4[4. Transition vers le Passwordless<br/>Clés FIDO2, Microsoft Authenticator sans mot de passe]
  1. Blocage définitif de l’authentification héritée :
    • Déployer une règle d’Accès Conditionnel bloquant l’accès pour tous les clients classés dans "Clients Exchange ActiveSync" et "Autres clients" (IMAP, POP, SMTP).
  2. Optimisation d’entra ID smart lockout :
    • Dans le portail Entra (Protection $\rightarrow$ Méthodes d'authentification $\rightarrow$ Protection par mot de passe), fixer le seuil de verrouillage à 5 ou 10 tentatives. Smart Lockout distingue les adresses IP familières des IP d’attaquants, bloquant ces dernières sans pénaliser l’utilisateur légitime.
  3. Migration vers l’authentification passwordless :
    • La suppression complète du mot de passe anéantit définitivement le modèle économique et opérationnel du password spraying.