Ce qui s’est passé — et surtout ce qui ne s’est pas passé
Entre le 16 et le 18 août 2026, un acteur se présentant sous le pseudonyme « TheHatman » a publié sur des forums cybercriminels des annonces de vente portant sur des annuaires internes complets, présentés comme extraits de tenants Azure/Entra ID de grands groupes internationaux — McDonald’s, Vodafone, TCS, HCL, Kyndryl, IHG, Gap, Hexaware, Wyndham figurent parmi les noms cités. Le volume cumulé annoncé se compte en millions d’enregistrements.
Les analystes de Hudson Rock / InfoStealers, qui ont examiné les échantillons publics, jugent ceux-ci crédibles : la structure des champs correspond à celle d’un export d’annuaire standard, et non à une compilation de fuites recyclées. Surtout, le contenu va bien au-delà du couple nom/e-mail : numéros de téléphone, matricules, rattachement hiérarchique (manager), appartenances de groupes, comptes de service. Autrement dit, une cartographie organisationnelle exploitable telle quelle.
Le point structurant pour les équipes sécurité est ailleurs : aucune vulnérabilité Azure, aucun 0-day, aucune faille de plateforme n’est en cause. Le vecteur décrit est banal — vol d’identifiants et de cookies/jetons de session par infostealer sur des postes utilisateurs, puis export massif via les portails et l’API Microsoft Graph. Ce que l’attaquant a exploité, ce sont les permissions par défaut d’Entra ID, qui autorisent un utilisateur membre standard à lire l’essentiel du répertoire.
Cet épisode s’inscrit dans une série 2026 déjà bien documentée côté identité Azure : la campagne de password spray visant l’application first-party Azure CLI (81 millions de tentatives entre le 12 et le 26 juin, 78 comptes compromis dans 64 organisations selon Huntress), et le durcissement par Microsoft, le 27 mars 2026, de l’évaluation des stratégies d’accès conditionnel « All resources » comportant des exclusions de ressources. Même fil rouge : le plan d’identité est le vrai périmètre, et les chemins d’authentification « techniques » sont la porte de service.
Pourquoi un simple compte utilisateur suffit
Dans un tenant Entra ID par défaut, le rôle implicite member user dispose de allowedToReadOtherUsers = true. Concrètement, un compte lambda authentifié peut appeler :
GET /v1.0/users— annuaire complet, avecdisplayName,mail,userPrincipalName,jobTitle,department,officeLocation,mobilePhone,employeeIdsi l’attribut est peuplé ;GET /v1.0/users/{id}/manageret/directReports— reconstruction de l’organigramme, arête par arête ;GET /v1.0/groupset/groups/{id}/members— segmentation métier, groupes d’administration, groupes de sécurité utilisés pour l’accès conditionnel ;GET /v1.0/servicePrincipals— inventaire des applications, y compris les intégrations SaaS et les comptes de service.
Rien de tout cela n’est une anomalie : c’est le contrat de fonctionnement de Teams, d’Outlook, de la recherche de personnes, de la plupart des outils internes. La différence entre un usage normal et une exfiltration tient uniquement au volume et à la cadence.
Les invités (guests) sont, eux, restreints par défaut depuis plusieurs années : le rôle guestUserRoleId vaut 10dae51f-b6af-4016-8d66-8c2a99b929b3 (« limited access »), qui interdit l’énumération générale du répertoire. Un troisième niveau, plus strict encore, existe : 2af84b1e-32c8-42b7-82bc-daa82404023b (« restricted »), qui limite l’invité aux objets dont il est membre ou propriétaire.
La chaîne d’attaque type
- Infostealer sur un poste (Lumma, Rhadamanthys, StealC et consorts), souvent via un installeur piégé ou une extension malveillante. Le malware exfiltre les mots de passe du navigateur et les cookies de session, y compris les artefacts de session Entra ID.
- Rejeu. Le cookie de session ou le refresh token permet de reprendre une session déjà authentifiée. Le MFA a été satisfait lors de l’émission du jeton : le rejouer ne le redéclenche pas. C’est le point le plus mal compris par les directions métier — « on a du MFA » ne protège pas contre le vol de jeton, seul un binding cryptographique (Token Protection, passkeys, certificats de device) le fait.
- Pivot vers un client public first-party. Plutôt que le portail, l’attaquant utilise un client OAuth public déjà consenti dans tous les tenants : Azure CLI (
04b07795-8ddb-461a-bbee-02f9e1bf7b46), Azure PowerShell, Microsoft Office. Aucun consentement à obtenir, aucune app registration à créer — donc aucune trace côtéAuditLogs. - Énumération Graph. Boucle sur
/users?$top=999en suivant@odata.nextLink, puis/groups, puis les appartenances. Quelques dizaines de milliers d’objets se récupèrent en minutes. - Export et revente.
Le device code flow mérite une mention particulière : conçu pour les appareils sans clavier, il permet à un attaquant de faire valider un code par une victime (phishing) et de récupérer un jeu de jetons complet, sur un client first-party, depuis n’importe où.
Réduire la surface lisible
1. Restreindre les permissions par défaut des membres
C’est la mesure au meilleur rapport gain/risque — et elle n’est pas exposée dans le portail : elle se pilote uniquement via Graph.
Connect-MgGraph -Scopes "Policy.ReadWrite.Authorization"
# État actuel
(Get-MgPolicyAuthorizationPolicy).DefaultUserRolePermissions | Format-List
# Couper la lecture d'annuaire pour les membres
Update-MgPolicyAuthorizationPolicy -DefaultUserRolePermissions @{
AllowedToReadOtherUsers = $false
AllowedToCreateApps = $false
AllowedToCreateSecurityGroups = $false
}
Ce qui casse, potentiellement : la recherche de personnes dans Teams, les organigrammes, Planner, Delve, et surtout les outils internes maison qui appellent Graph avec un jeton délégué. À l’inverse, la GAL Exchange Online s’appuie sur une copie d’annuaire distincte et reste généralement fonctionnelle — ce qui rend le test en production trompeusement rassurant si l’on ne valide que Outlook.
Méthode : inventorier d’abord les appelants délégués via MicrosoftGraphActivityLogs, migrer les outils légitimes vers des permissions applicatives (User.Read.All sur un service principal dédié, contrôlé), puis basculer le paramètre sur un tenant de test, puis en production avec une fenêtre de rollback documentée.
2. Restreindre les portails et les invités
Le paramètre Restrict access to Microsoft Entra administration portal empêche les non-administrateurs d’ouvrir le centre d’administration. Utile contre l’exploration opportuniste, mais il ne bloque ni Graph ni PowerShell : ce n’est pas un contrôle de sécurité, c’est un réducteur de bruit. Passez en parallèle les invités en rôle « restricted » si vos scénarios de collaboration externes le permettent.
3. Unités administratives à gestion restreinte
Les restricted management administrative units (Entra ID P1) permettent d’isoler un ensemble d’objets — comptes de service, comptes à privilèges, VIP — de sorte que même les détenteurs de rôles à portée tenant ne puissent pas les administrer sans affectation explicite. C’est la contre-mesure aux escalades latérales une fois un compte d’admin intermédiaire compromis.
4. Hygiène des attributs
Un annuaire volé ne fait mal qu’en proportion de ce qu’on y a mis. Cessez de stocker matricules RH, identifiants de badge, données de rattachement sensibles ou — cela arrive encore — des secrets dans extensionAttributes et les champs libres. Auditez : Get-MgUser -All -Property "onPremisesExtensionAttributes" puis comptez les valeurs distinctes non nulles.
Verrouiller les chemins d’authentification
- Une stratégie d’accès conditionnel « All resources » sans exclusion de ressource. Chaque exclusion est un chemin d’authentification alternatif. Le changement Microsoft du 27 mars 2026 a précisément durci l’évaluation de ces stratégies afin qu’une exclusion ne serve plus de tremplin : jusque-là, obtenir un jeton pour une ressource exclue pouvait, via les refresh tokens partagés entre clients de la même famille, ouvrir l’accès à d’autres ressources théoriquement couvertes. Reprenez l’inventaire de vos exclusions : certaines n’ont plus de raison d’être, d’autres cassaient silencieusement votre couverture.
- Bloquer l’authentification héritée et le flux ROPC (
Resource Owner Password Credentials), qui transmet le mot de passe en clair au client et court-circuite l’expérience MFA. - Restreindre le device code flow via une stratégie CA de type authentication flows, en n’autorisant que les populations qui en ont un besoin avéré (kiosques, appareils partagés).
- Named locations sur le plan de management (Microsoft Admin Portals, Azure Management, Graph applicatif) pour les rôles à privilèges.
- Token Protection et Continuous Access Evaluation (CAE) : le premier lie le jeton à l’appareil, le second permet la révocation quasi temps réel côté ressource.
- Comptes break-glass exclus de toutes ces stratégies, avec alerte sur toute connexion.
Détecter l’énumération
Sans journalisation Graph, l’énumération est invisible : les SigninLogs montrent une connexion légitime, les AuditLogs ne montrent rien (aucune écriture). Activez dans les paramètres de diagnostic d’Entra ID les catégories MicrosoftGraphActivityLogs et AADGraphActivityLogs (licence P1 requise pour la première), avec export vers Log Analytics.
Volumétrie d’appels annuaire par principal :
MicrosoftGraphActivityLogs
| where TimeGenerated > ago(24h)
| where RequestMethod == "GET"
| where RequestUri has_any ("/users", "/groups", "/servicePrincipals", "/directoryObjects", "/directoryRoles")
| summarize Appels = count(),
Octets = sum(ResponseSizeBytes),
UrisDistinctes = dcount(RequestUri),
IPs = make_set(IPAddress, 5)
by UserId, AppId, bin(TimeGenerated, 1h)
| where Appels > 300 or Octets > 20 * 1024 * 1024
| order by Octets desc
Pagination en rafale — signature la plus fiable d’un dump :
MicrosoftGraphActivityLogs
| where TimeGenerated > ago(7d)
| where RequestUri has "$skiptoken" or RequestUri has "$top=999"
| summarize Pages = count(), Debut = min(TimeGenerated), Fin = max(TimeGenerated)
by UserId, AppId, ApiVersion
| extend DureeMin = datetime_diff('minute', Fin, Debut)
| where Pages > 20 and DureeMin < 30
Connexions device code sur client first-party :
SigninLogs
| where TimeGenerated > ago(30d)
| where AuthenticationProtocol == "deviceCode"
| summarize Connexions = count(), Pays = make_set(Location, 10)
by UserPrincipalName, AppDisplayName, AppId
| order by Connexions desc
Filtrer le bruit avant de définir des seuils : les connecteurs de synchronisation RH, les outils ITSM, les solutions de gouvernance des identités et certaines applications Microsoft génèrent légitimement des dizaines de milliers d’appels quotidiens. Construisez une baseline sur 14 à 30 jours par couple (AppId, UserId) et alertez sur l’écart, pas sur une valeur absolue. Un signal fort et peu bruyant : un AppId de client public (Azure CLI, Azure PowerShell) associé à un volume de pagination sur /users — ce profil n’a quasiment jamais de justification métier.
Runbook de réponse
- Révoquer sessions et jetons.
Revoke-MgUserSignInSessioninvalide les refresh tokens, pas les access tokens déjà émis, qui restent valides jusqu’à leur expiration (typiquement 60 à 90 minutes). C’est exactement la fenêtre que CAE referme : sans CAE, l’attaquant conserve son accès Graph pendant une heure après votre « révocation ». - Réinitialiser le mot de passe et, si le poste est suspect, isoler la machine avant toute réauthentification.
- Rotation des secrets des comptes de service et des applications visibles dans l’export.
- Chasse à la persistance : nouvelles
app registrations, ajout depasswordCredentialsoukeyCredentialssur des service principals existants, nouveaux propriétaires d’applications, règles de transfert de boîte aux lettres, méthodes MFA ajoutées. - Calculer le périmètre exfiltré à partir des logs Graph : la somme des
ResponseSizeByteset l’ensemble desRequestUripar session donnent une estimation défendable de ce qui est sorti — indispensable pour la qualification RGPD.
Quand l’annuaire est déjà dehors
Un annuaire complet ne se révoque pas. Il transforme durablement le profil de risque :
- Spear-phishing contextualisé : l’attaquant connaît le manager, le service, le numéro de mobile. Les scénarios « votre N+1 vous demande… » deviennent crédibles.
- Fraude au support, façon Scattered Spider : appel au helpdesk avec matricule, manager et localisation corrects pour obtenir une réinitialisation MFA.
Deux contre-mesures concrètes : imposer au helpdesk une vérification qui ne repose pas sur des données d’annuaire (validation par le manager via un canal authentifié, code temporaire dans une application déjà enrôlée, vérification vidéo), et communiquer en interne — les collaborateurs doivent savoir que la connaissance de leur organigramme par un interlocuteur ne prouve plus rien.
Checklist en 15 points
allowedToReadOtherUsers = false(après inventaire des appelants délégués).allowedToCreateApps = false,allowedToCreateSecurityGroups = false.- Invités en rôle restricted ou a minima limited.
restrictNonAdminAccessactivé sur le centre d’administration Entra.- Restricted management AU sur comptes à privilèges, VIP et comptes de service.
- Attributs sensibles purgés des champs d’extension.
- Stratégie CA « All resources » sans exclusion de ressource, exclusions restantes justifiées et datées.
- Authentification héritée et ROPC bloqués.
- Device code flow restreint par stratégie CA authentication flows.
- Token Protection et CAE activés là où c’est supporté.
- Named locations sur le plan de management.
- Comptes break-glass exclus, alertés, testés trimestriellement.
MicrosoftGraphActivityLogsetAADGraphActivityLogsexportés vers Log Analytics, rétention ≥ 90 jours.- Règles d’alerte sur volumétrie
/users–/groups, pagination en rafale, device code sur client first-party. - Runbook de révocation testé, incluant la rotation des secrets applicatifs.
Commandes de vérification rapide :
# Permissions par défaut
(Get-MgPolicyAuthorizationPolicy).DefaultUserRolePermissions
(Get-MgPolicyAuthorizationPolicy).GuestUserRoleId
# Stratégies d'accès conditionnel comportant des exclusions de ressources
Get-MgIdentityConditionalAccessPolicy -All |
Where-Object { $_.Conditions.Applications.ExcludeApplications.Count -gt 0 } |
Select-Object DisplayName, State,
@{n='Exclusions';e={$_.Conditions.Applications.ExcludeApplications -join ','}}
# Credentials ajoutés récemment sur des service principals
Get-MgServicePrincipal -All -Property "id,displayName,passwordCredentials,keyCredentials" |
Where-Object { $_.PasswordCredentials.StartDateTime -gt (Get-Date).AddDays(-30) } |
Select-Object DisplayName, Id
# Paramètres de diagnostic sur le tenant Entra
az monitor diagnostic-settings list \
--resource "/providers/Microsoft.aadiam/diagnosticSettings" -o table
La campagne TheHatman n’apporte aucune technique nouvelle : elle industrialise une évidence que la plupart des tenants n’ont jamais corrigée depuis leur création — l’annuaire est lisible par défaut, et son exfiltration ne produit aucun événement d’audit. Les deux chantiers à ouvrir sont donc dissymétriques : couper allowedToReadOtherUsers est une décision de quinze minutes mais un projet de plusieurs semaines à cause des dépendances applicatives ; activer MicrosoftGraphActivityLogs est une case à cocher qui, seule, fait passer votre organisation de l’aveuglement total à la détection. Si vous ne devez faire qu’une chose cette semaine, commencez par la seconde — sans elle, vous ne saurez jamais si votre annuaire est déjà en vente.
Commentaires (0)
Veuillez vous connecter pour laisser un commentaire.
Se connecterPas encore de commentaires. Soyez le premier à commenter !