Les journaux d’activité du graphe AAD sont désormais ingestibles dans Elastic et utilisables pour la détection des menaces dans la solution SIEM/XDR. Cette phrase ne devrait pas être excitante, mais elle l’est. Pendant la majeure partie de la dernière décennie, cette tranche de télémétrie n’existait tout simplement pas en tant que flux de journal accessible aux clients. Microsoft Graph Activity Logs (la surface moderne graph.microsoft.com ) est devenu GA en avril 2024. L’héritage graph.windows.net surface, celui que les outils adverses touchent réellement, est resté sombre jusqu’au début de 2026.
Cet article parcourt la boucle de bout en bout. Pourquoi la visibilité est importante, comment ingérer les journaux dans Elastic, comment générer une reconnaissance réaliste manuellement et avec ROADrecon, et comment rechercher le résultat dans ES|QL. Tout ce qui est ci-dessous a été validé par rapport à un locataire vivant.
Principaux points abordés dans cet article
-
Les journaux d’activité AAD Graph sont intégrés à Elastic via l’intégration Azure et atterrissent dans
logs-azure.aadgraphactivitylogs-*avec une extraction ECS complète. -
ROADtools, AADInternals et amis opèrent dans un vide de visibilité depuis des années. Les défenseurs ne captaient pas les appels.
-
AAD Graph est « obsolète » mais reste interrogable dans la plupart des locataires. La version interne de l’API 1.61 renvoie toujours des données que Microsoft Graph ne renvoie pas.
-
Les champs ECS sont typés (
event.action,event.outcome,http.request.method,source.ip,user.id,user_agent.original). Les extras de jeux de données restent consultables sousazure.aadgraphactivitylogs.properties.*. -
Cinq chasses détectent de manière fiable l’activité : outils-agents-utilisateurs, étendue des points de terminaison,
*-internalmauvaise utilisation de l’API, incompatibilités FOCI client-ID, et pics 4xx.
Une brève histoire de la visibilité des défenseurs
Les défenseurs ont passé des années à s’inscrire, à accéder sous condition, à attribuer des rôles et à obtenir des accords de consentement OAuth. Très peu de contenu couvre les API de répertoire sous-jacentes que les outils adverses touchent réellement. La raison est structurelle : les journaux accessibles aux clients pour ces API n’existaient pas. Microsoft Graph Activity Logs a été posé en premier (aperçu octobre 2023, GA avril 2024). AzureADGraphActivityLogs est finalement apparu début 2026.
Pendant la majeure partie de la dernière décennie, l’énumération des graphes AAD était invisible pour les SOC, non pas parce que la télémétrie était cachée, mais parce qu’elle n’existait pas. ROADtools, AADInternals, MSOLSpray, Microburst. Aucun d’entre eux ne produisait de données que quiconque pouvait capturer, même avec une configuration de journalisation parfaite.
Cela change le jour où AzureADGraphActivityLogs commence à apparaître dans votre index de plateforme-logs.
AAD Graph est « obsolète » mais toujours très présent
Petite mise à jour. Azure AD Graph est l’API REST héritée pour les objets du répertoire Entra ID, hébergée à https://graph.windows.net/{tenantId}/{objecttype} avec des versions API telles que 1.5, 1.6 et 1.61-interne. Microsoft demande à tout le monde de migrer vers Microsoft Graph depuis 2019, et la date de retrait a été repoussée à plusieurs reprises.
La dépréciation n’a pas disparu. En 2026, AAD Graph peut encore répondre aux requêtes dans des environnements où des chemins d’accès hérités restent disponibles ou où les applications n’ont pas été explicitement bloquées de son utilisation. Voici quelques raisons pour lesquelles il reste une cible pour les attaquants :
-
Les outillages adversaires n’ont pas été portés. ROADrecon l’utilise toujours pour
gather. AADInternals a des dizaines de cmdlets qui l’emballent. -
Les versions de l’API
*-internalrenvoient plus de données.1.61-internalexposestrongAuthenticationDetailen ligne sur l’objet utilisateur lors d’une marche normale dans le répertoir. L’équivalent Microsoft Graph se trouve derrière un point de terminaison /authentication/methods séparé, verrouillé parUserAuthenticationMethod.Read.All. Cette asymétrie est exactement ce que exploite l’outil d’énumération en masse. -
Le blocage n’est pas un simple bascule. Le
blockAzureADGraphAccesscontrôle chaque application surapplication.authenticationBehaviors, donc bloquer à l’échelle du locataire signifie itérer chaque enregistrement d’application. La plupart des environnements ne l’ont pas fait car certaines automatisations héritées dépendent encore de l’API. L’application progressive de la retraite de Microsoft fait le travail selon le calendrier de Microsoft, pas celui du défendeur. -
La visibilité n’existait pas, donc les équipes rouges et les adversaires pouvaient marteler les points de terminaison de l’API pour obtenir des informations pertinentes.
Le trafic AAD Graph légitime est dominé par une poignée d’appelants Microsoft first-party. Dans notre locataire test, l’ordre, par volume, était Microsoft.OData.Client, Microsoft Azure Graph Client Library, une queue UA vide provenant des AppIds first-party, Microsoft ADO.NET Data Services, et le portail Azure (Chrome UAs contre l’ID de l’application portail). Tout ce qui est en dehors de cet ensemble reconnaissable est soit un outil interne, soit une activité non autorisée. Cela en fait un jeu de données solide pour la chasse/détection des menaces. Si tu es en train de le capturer.
Mise en place du pipeline d’ingestion
Si vous utilisez déjà l’intégration Elastic Azure avec les paramètres de diagnostic redirigés vers un hub d’événements, parcourez rapidement cette section. Il vous suffit probablement d’activer une catégorie de journal supplémentaire. De zéro, c’est un trajet d’environ 20 minutes.
Étape 1 : Une pile pour recevoir les journaux
Tout déploiement Elastic fonctionne. Un essai Elastic Cloud est l’option à faible friction pour le prototypage. Une autre option est le projet Elastic Container pour commencer. L’intégration Azure gère déjà AzureADGraphActivityLogs une fois activée.
Étape 2 : Ajouter l’intégration Azure
Dans Kibana, les intégrations > Azure Logs > ajouter Azure Logs. Branchez votre chaîne de connexion Event Hub, le nom Event Hub et un compte Storage pour le checkpointing décalé, le tout sur un event hub dans le même abonnement que votre locataire.
Activez spécifiquement le flux de données Azure Logs v2. C’est le point d’entrée pour les journaux d’activité des graphes AAD. Le routeur d’événements correspond category == "AzureADGraphActivityLogs" et redirige les documents vers logs-azure.aadgraphactivitylogs-*, où le pipeline de jeu de données applique une extraction complète de l’ECS.
Nous avons également décomposé les logs d’activité graphiques Azure AD en un élément d’intégration à part, afin que vous puissiez chercher « Azure AD Graph Activity Logs » et installer directement via le modèle de politique.
Étape 3 : Activez les paramètres de diagnostic sur Entra ID
C’est l’étape que la plupart des défenseurs manquent. AzureADGraphActivityLogs en tant que catégorie diagnostic-settings est plus récente. Même si vos paramètres de diagnostic Entra ID ont été configurés depuis un certain temps, la nouvelle catégorie a besoin d’un nouveau tick. Sinon, les données survivent et meurent dans la limite du tenant de Microsoft.
Dans le portail Azure :
- Entra ID > Surveillance > paramètres de diagnostic > + Ajout de paramètres de diagnostic.
- Nommez-le.
- Dans Logs, vérifiez AzureADGraphActivityLogs. Pendant que vous y êtes, MicrosoftGraphActivityLogs, SignInLogs et AuditLogs valent la peine d’être activés s’ils ne le sont pas déjà. L’intégration gère tout cela.
- Dans Détails de la destination, diffusez vers un hub d’événements (le même que l’étape 2).
- Sauvegarder.
Étape 4 : Vérifier que les données circulent
En quelques minutes, vous devriez commencer à voir des événements. Test de santé mentale le plus rapide :
FROM logs-azure.aadgraphactivitylogs-*
| LIMIT 20
Si les documents reviennent avec des champs event.action, http.request.methodet zure.aadgraphactivitylogs.properties.* remplis, c’est bon. Si rien n’apparaît, les suspects habituels sont une permission oubliée du hub d’événements, une faute de frappe dans la chaîne de connexion, ou la catégorie AAD Graph qui n’est tout simplement pas cochée.
Pour forcer quelques événements, connectez-vous au portail Azure et cliquez sur Utilisateurs ou Applications. Le portail appelle toujours AAD Graph en interne pour certains détails d’objets. Si cela ne génère rien, cette boucle de rotation va :
TOKEN=$(az account get-access-token --resource https://graph.windows.net --query accessToken -o tsv)
TID=$(az account show --query tenantId -o tsv)
for obj in users groups servicePrincipals applications tenantDetails; do
curl -sS -o /dev/null -H "Authorization: Bearer $TOKEN" \
"https://graph.windows.net/$TID/$obj?api-version=1.6&\$top=5"
done
Forme du champ
Une fois les données en flux, les propriétés apparaissent comme des champs de premier niveau typés. Celles qui comptent pour la chasse :
- ECS, peuplé directement :
event.action(un verbe sémantique dérivé de méthode + collection, par exempleusers-read, batch-execute),event.outcome,event.duration,http.request.method,http.response.status_code, source.ip, etsource.geo.*, user.id, user_agent.original(plus des sous-champs analysés),url.path, azure.tenant_id, cloud.service.name = "Azure AD Graph". - Spécifique à chaque ensemble de données sous
zure.aadgraphactivitylogs.properties.*: app_id,,app_id,api_version,actor_type,roles,scopes,wids,identity_provider,client_auth_method,sign_in_activity_id,token_issued_at. related.userobtient à la foisuser.idetproperties.app_id, donc les pivots sur la dimension OAuth du client travaillent parallèlement au pivot utilisateur.
Le JSON brut reste en event.original pour la rediffusion forensique. Vous ne devriez pas avoir besoin de puiser dedans pour la chasse normale. Si oui, ES|Le JSON_EXTRACT() de QL est le levier.
Énumération des graphes AAD avec ROADrecon
Pour savoir quoi chasser, il faut savoir à quoi ressemble l’activité. Les deux kits à outils ci-dessous sont les sources les plus courantes de trafic AAD Graph dans les flux de travail de recherche sur les équipes rouges et la sécurité. J’ai utilisé les deux contre notre locataire de test.
Note : Je n’assume aucune responsabilité pour une mauvaise utilisation de ce code. Utilisez ces outils uniquement contre des locataires que vous possédez ou dont vous avez une autorisation écrite explicite pour tester.
ROADrecon : Test d’énumération en masse
ROADrecon est le module de collecte de données de ROADtools, le cadre de recherche Entra ID de Dirk-jan Mollema. Fortement recommandé si vous ne l’avez pas utilisé. gather parcourt chaque type d’objet intéressant dans le répertoire (utilisateurs, groupes, principaux de service, applications, appareils, rôles de répertoire, assignations de rôles, assignations de rôles éligibles, autorisations OAuth2, unités administratives) et écrit le résultat dans SQLite.
La configuration est le flux de travail standard :
pip install roadrecon
roadrecon auth --device-code -c 04b07795-8ddb-461a-bbee-02f9e1bf7b46 -r https://graph.windows.net
Le flux de code de l’appareil vous donne une URL et un code. Nous utilisons la ligne de ligne de ligne Microsoft Azure comme référence par défaut (1b730954-1685-4b74-9bfd-dac224a7b894 - AAD PowerShell), qui a renvoyé des 403 dans notre locataire. Après la connexion :
roadrecon gather
En exécutant la réunion, le jeton obtenu est proprement complété. Du point de vue du locataire, la série a produit un peu plus de ~2 000 appels et journaux AAD Graph en environ 1 minute. Énumération en masse pour chaque type d’objet que ROADrecon connaît.
À partir de là, nous pouvons former quelques premières détections pour commencer à signaler ces anomalies.
Champs clés pour la détection de menaces dans les graphes AAD
Avant les chasses, voici quelques champs de départ solides pour détecter les anomalies.
| Champ | Description | Ce que vous pouvez trouver |
|---|---|---|
event.action | Verbe sémantique (méthode HTTP + collection, par exemple, 'users-read, batch-execute) | Un filtre bon marché pour isoler l’activité du graphe AAD selon l’intention |
http.request.method | OBTENIR, POSTER, PATCHER, SUPPRIMER | Lectures (reconnaissance) vs écritures (modification, injection de créances, persistance) |
http.response.status_code | État HTTP retourné | Reconnaissance réussie vs bloquée ; Les rafales de 4xx indiquent un sondage de permissions ou un coup de force brute |
user.id | Appel de l’ID d’objet de répertoire de l’utilisateur | Attribution de l’identité ; pivot vers les autres activités de cet utilisateur dans les logs de connexion / auditlogs |
user_agent.original | Chaîne d’UA complète de l’appelant | Que l’appelant soit une bibliothèque Microsoft first-party, un outil de développement (curl, Python aiohttp) ou un outil offensif connu |
url.path | Chemin de ressources (/users, /policies, /servicePrincipals, ...) | Quels types d’objets de répertoire sont touchés ; La largeur à travers des chemins distincts indique une énumération massive |
azure.aadgraphactivitylogs.properties.app_id | OAuth client ID qui a émis le jeton | Que le trafic provienne d’un client propriétaire légitime ou d’un chemin d’abus à la manière d’un échange de FOCI |
azure.aadgraphactivitylogs.properties.api_version | 1.5, 1.6, 1.61-interne, etc. | Que l’appelant demande des champs uniquement internes (strongAuthenticationDetail, ensemble complet de CAP) que les outils adverses ciblent spécifiquement |
azure.aadgraphactivitylogs.properties.actor_type | Utilisateur, Application, ServicePrincipal | Appelant humain vs flux principal de service / application uniquement |
azure.aadgraphactivitylogs.properties.roles / wids | Noms d’affichage des rôles d’annuaire et modèles de GUID bien connus détenus par l’appelant | Qu’un rôle privilégié (Administrateur Global, Administrateur d’Application, etc.) soit exercé au moment de l’appel |
azure.aadgraphactivitylogs.properties.scopes | OAuth s’étend sur le jeton appelant | Quelles permissions de répertoire le jeton accorde réellement à l’appelant |
azure.aadgraphactivitylogs.properties.client_auth_method | Comment le client s’est authentifié (PRT, certificat, secret, ...) | Empreintes digitales pour abus de PRT, exploitation de dispositifs PRT ou vol de crédentiels clients |
azure.aadgraphactivitylogs.properties.sign_in_activity_id | L’identifiant de corrélation avec la connexion d’origine | Pivot d’un appel AAD Graph vers l’événement de connexion qui a produit le jeton appelant |
azure.aadgraphactivitylogs.properties.token_issued_at | Horodatage : le jeton a été frappé | Analyse de l’âge des jetons ; Les appels circulant sur un token émis il y a quelques jours peuvent indiquer un abus de token obsolète / de rafraîchissement |
Détection et prévention
Détection
La condition préalable à toute détection de graphes AAD est d’avoir les journaux dès le départ. La catégorie de diagnostic AzureADGraphActivityLogs doit être activée dans Entra ID et acheminée vers une destination que vous pouvez interroger (au minimum un espace de travail Log Analytics, idéalement également transféré vers un hub d’événements pour l’ingestion Elastic comme décrit dans la section de configuration ci-dessus). Jusqu’à ce que cela soit fait, les appels décrits dans ce post se déroulent entièrement hors caméra, et aucune des chasses ci-dessous ne s’active.
Si vous ne pouvez pas ingoter dans Elastic pour le moment, activez quand même le paramètre de diagnostic et envoyez à Log Analytics. Les équivalents KQL des chasses ci-dessous sont simples, et les données s’accumulent avec rétention même sans traitement supplémentaire.
La prévention
Il n’y a pas de kill switch AAD Graph à l’échelle du locataire dans le portail. Le contrôle réel de la couche application est :
application.authenticationBehaviors.blockAzureADGraphAccess
Un Boolean par application sur la ressource applicative (Microsoft Graph bêta, docs). Bloquer à grande échelle signifie parcourir chaque inscription d’application et la retourner manuellement ou programmatiquement. La retraite progressive de Microsoft fait cela dans leur calendrier quoi qu’il arrive. Plus cela avance, moins il y a de surface à défendre.
Les défenseurs peuvent se déplacer sur les mêmes axes en attendant :
-
Auditez les applications dans votre locataire qui détiennent encore des jetons pendant graph.windows.net. Mets
blockAzureADGraphAccess = truesur ceux qui n’en ont pas besoin. Tout ce qui dépend encore du graphe AAD casse bruyamment, ce qui révèle une automatisation héritée dont vous ne saviez pas exister. -
Appliquez l’accès conditionnel avec Azure AD Graph comme ressource cible. Le principal de service Azure AD Graph (
00000002-0000-0000-c000-000000000000) n’apparaît pas dans le sélecteur standard d’application CA, mais il est couvert par les politiques All Resources et est ciblable individuellement via l’approche personnalisée de filtre d’attributs de sécurité. Le changement d’application de Microsoft du 2026 mars rend cela plus pratique : les champs à faible privilège (User.Read, People.Read, etc.) qui étaient auparavant auto-exclus de l’application CA sont désormais considérés comme un accès AAD Graph, donc toutes les politiques de ressources les bloquent en réalité. La CA évalue lors de l’émission des tokens, donc les tokens déjà valides continuent de fonctionner jusqu’à leur expiration. -
Appliquez la CA aux clients FOCI sur lesquels l’outillage adversaire repose (Microsoft Teams, Microsoft Office, OneDrive, Azure PowerShell, etc.). Exigez des dispositifs gérés et conformes. Le chemin de swap s’effondre si le client sous-jacent ne peut pas se connecter.
-
Pour les appelants principaux de service, Workload Identities Premium ajoute une CA portée portée aux principaux de service. Les conditions sont limitées à la localisation, au risque de protection d’identité et au contexte d’authentification ; le seul contrôle de subvention est Blocage. Utile pour effondrer les chemins externes et contextuels risqués, pas pour définir un SP vers des applications cloud spécifiques comme le fait l’AC utilisateur.
-
Désactivez le flux de code de l’appareil pour les utilisateurs qui n’en ont pas besoin.
roadrecon auth --device-codeest le chemin de moindre résistance dans tout le pipeline ci-dessus et est extrêmement courant dans le phishing OAuth.
Détection des comportements
Nous avons livré des règles de détection couvrant les formes de reconnaissance AAD Graph documentées ci-dessus. Chacune vit dans le dépôt de règles de détection Elastic et s’exécute nativement sur le flux de données analysé logs-azure.aadgraphactivitylogs-* .
Azure AD Graph Access with Suspicious User-Agent - KQL match rule. Se déclenche lorsque AAD Graph reçoit du trafic provenant de chaînes utilisateur-agent correspondant à des familles d’outils offensives (Python, aiohttp, curl, Go-http-client, axios, AzureHound, BloodHound, AADIntenals, etc.). Signal de base solide car aucun composant Microsoft propriétaire ne s’identifie comme l’un de ces éléments, alors que les outils par défaut le font.
Azure AD Graph Taux d’erreur élevé de 4xx de l’utilisateur - ES|Agrégation QL. Se déclenche lorsqu’un seul appelant produit un ratio exceptionnellement élevé de réponses 4xx par rapport au graphique AAD en une fenêtre de courte période. L’utilisation de tokens de reconnaissance et de force brute laisse une traînée de 403 et 404 alors que les outils parcourent les points de terminaison pour lesquels ils n’ont pas d’autorisation, demandent des ID d’objet qu’ils n’ont pas, ou utilisent un ID client non autorisé pour AAD Graph.
Accès au graphe Azure AD avec client et utilisateur inhabituels - règle KQL new_terms, sévérité moyenne. Se déclenche lorsqu’une paire (client OAuth appelant, utilisateur connecté) apparaît sur le graphique AAD pour la première fois dans les 14 jours précédents. Capture les échanges FOCI, les tokens de rafraîchissement modifiés pour des clients que l’utilisateur n’utilise pas normalement, et les tokens volés utilisés par des clients inconnus. Ignore les applications first-party connues qui étaient couramment observées en interaction avec Azure AD et qui sont en backend détenues par Microsoft.
Azure AD Graph Access avec utilisateur inhabituel et ASN - règle de correspondance KQL. Exclut les organisations ASN courantes de Microsoft / AWS / GCP / Akamai / Cloudflare et signale le trafic AAD Graph provenant de l’extérieur de cet ensemble. Les outils adverses reposent généralement sur des FAI résidentiels, des fournisseurs VPS ou des réseaux anonymisants qui produisent une distribution ASN différente de celle des appelants first-party légitimes. Ajustable par locataire en ajustant la liste ASN exclue.
Azure AD Graph Potential Enumeration (ROADrecon) - ES|Agrégation QL, haute sévérité. Nécessite à la fois un agent utilisateur aiohttp et une rafale de 500+ requêtes AAD Graph provenant d’une seule identité. La commande gather de ROADrecon utilise par défaut aiohttp et parcourt chaque type d’objet de répertoire, donc la combinaison est essentiellement une empreinte digitale d’outil. Sévérité plus élevée que la règle générique non Microsoft UA car l’exigence supplémentaire de rafale supprime la classe faux positif développeur-prototype.
Entrée ID OAuth Device Code Sign-in to Azure AD Graph Enumeration - séquence EQL, séquence de haute intensité. Rejoint une connexion réussie par code de l’appareil à l’audience Graph AAD héritée (00000002-0000-0000-c000-000000000000) sur un appareil non géré avec l’énumération des annuaires contre graph.windows.net par le même utilisateur en cinq minutes. Le phishing par code de dispositif atterrit un jeton OAuth sans toucher au mot de passe ou au MFA de l’utilisateur, de sorte que les lectures immédiates de graphes des utilisateurs, des principaux de service, des applications, des attributions de rôles, des politiques ou des détails du locataire sous ce jeton correspondent à l’identité compromise pilotée par l’attaquant. La séquence cross-data-stream supprime la classe de faux positif à événement unique que portent les autres règles AAD Graph.
Visibilité du graphique AAD : la suite
Pendant la majeure partie de la dernière décennie, l’activité des graphes AAD était l’équivalent télémétrique de la matière noire. Nous savions qu’elle existait parce que les outils adverses ne cessaient de le pointer, mais les clients n’avaient aucun flux de diagnostic auquel s’abonner ni de journaux à interroger. Microsoft Graph Activity Logs a comblé la moitié de l’écart lors de leur passage en GA en avril 2024. AzureADGraphActivityLogs a finalement fermé l’autre moitié début 2026.
Maintenant que les données existent, le reste dépend de nous. Ajoutez le nouveau paramètre de diagnostic, pointez-le vers un hub d’événements, intégrez votre pile, activez les détections (ou créez-en les vôtres) et passez à la surveillance.
Les détections de ce post sont un point de départ. Une fois que le trafic AAD Graph arrive dans votre pile et que vous avez une base de ce à quoi ressemble la normale dans votre locataire, les mêmes schémas se généralisent. Les appels Microsoft officiels légitimes forment un petit groupe reconnaissable, et tout ce qui se trouve en dehors de cet ensemble mérite un examen plus attentif.
L’activité était toujours là. La visibilité l’est enfin aussi.
Bonne chasse !
Références
Les éléments suivants ont été référencés tout au long de la recherche ci-dessus :
- Elastic Azure Integration
- ROADtools GitHub
- Wiki ROADtools
- BloodHound avec des capacités Azure AD
- AADInternals
- Documentation AADInternals
- Migrez vos applications d’Azure AD Graph vers Microsoft Graph
- Configurez les paramètres de diagnostic Microsoft Entra pour les journaux d’activité
- Accéder aux journaux d’activité Microsoft Graph
- Les journaux d’activité Microsoft Graph sont désormais généralement disponibles
- Le chaînon manquant : AADGraphActivityLogs arrive enfin
- Escalade des privilèges Azure AD - Prise en charge des permissions d’application par défaut en tant qu’administrateur d’application
- Abuser d’Azure AD SSO avec le jeton de rafraîchissement primaire
À propos d'Elastic Security Labs
Elastic Security Labs est la branche renseignement sur les menaces d’Elastic Security dédiée à créer un changement positif dans le paysage des menaces. Elastic Security Labs propose des recherches publiques sur les menaces émergentes avec une analyse des objectifs stratégiques, opérationnels et tactiques adversaires, puis intègre cette recherche aux capacités intégrées de détection et de réponse d’Elastic Security. Suivez Elastic Security Labs sur Twitter @elasticseclabs et consultez nos recherches sur www.elastic.co/security-labs/.