☁️Entra IDApplicationsPermissionsMonitoring

Permissions Graph API dangereuses App Registration Entra : détection et remédiation

Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All et RoleManagement.ReadWrite.Directory peuvent transformer un identifiant d'application divulgué en contrôle total Global Administrator. Voici comment fonctionne cette escalade, comment détecter ces attributions et comment y remédier.

Younes AZABARPar Younes AZABAR10 min de lecture
Permissions Graph API dangereuses App Registration Entra : détection et remédiation

Les permissions Graph API dangereuses App Registration Entra transforment un simple clic de consentement admin en un identifiant permanent, valable sur tout le tenant. Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All et RoleManagement.ReadWrite.Directory sont des permissions applicatives (app-only) — des attributions qui permettent à un service principal d'agir sur l'ensemble d'un tenant Microsoft 365, sans utilisateur connecté et sans délimitation par objet. Ce guide détaille ce que chaque permission autorise réellement, une chaîne d'attaque documentée qui les enchaîne jusqu'au contrôle complet Global Administrator, et comment détecter et corriger ces attributions.

Permissions Graph API dangereuses App Registration Entra expliquées

Les quatre sont des permissions applicatives, aussi appelées permissions app-only. La documentation Graph de Microsoft elle-même trace la ligne clairement : les permissions applicatives « fonctionnent dans un scénario d'accès app-only, sans utilisateur connecté présent », et l'application « peut accéder à toutes les données associées à la permission ». Une permission déléguée est bornée par ce que l'utilisateur connecté peut déjà voir ; une permission applicative n'est bornée par personne.

Les quatre permissions nécessitent un consentement admin, et Microsoft restreint qui peut les accorder aux rôles Privileged Role Administrator et Global Administrator. Ce simple clic de consentement — souvent donné une seule fois, lors de l'onboarding, par la personne qui se trouvait dans la pièce — est ce qui transforme une App Registration en une attribution d'accès permanente, valable sur tout le tenant, que plus personne ne revoit.

PermissionTypeCe qu'elle autorise réellement (description de Microsoft)
Directory.ReadWrite.AllApplicationLire et écrire les données d'annuaire — utilisateurs, groupes et plus — sans utilisateur connecté. Microsoft classe cette permission au deuxième rang en niveau de privilège global parmi les permissions Entra ID, juste derrière la permission déléguée la plus privilégiée.
Mail.ReadWriteApplicationCréer, lire, modifier et supprimer des e-mails dans toutes les boîtes aux lettres du tenant, sans utilisateur connecté.
Files.ReadWrite.AllApplicationLire, créer, modifier et supprimer tous les fichiers de toutes les collections de sites, sans utilisateur connecté.
RoleManagement.ReadWrite.DirectoryApplicationLire et écrire toutes les données de gestion des rôles de l'annuaire — y compris activer des attributions de rôle éligibles et gérer les attributions de rôle Entra — sans utilisateur connecté.

Source : référence des permissions Microsoft Graph.

⚠️

⚠️ Avertissement : ce ne sont pas des permissions obscures qu'un attaquant doit découvrir — ce sont des entrées standard du sélecteur de permissions Graph, accordées via la même boîte de dialogue de consentement admin que toutes les autres. Le danger réside entièrement dans le rayon d'impact, pas dans le mécanisme.

Comment ça fonctionne

Une permission applicative s'attache à un service principal, l'identité locale au tenant d'une App Registration. Une fois accordée, le service principal s'authentifie avec son propre identifiant — un client secret ou un certificat — via le flux OAuth 2.0 client credentials. Le token d'accès obtenu porte la permission dans sa revendication (claim) roles, et Microsoft Graph applique l'accès sur la seule base de cette revendication. Il n'y a aucun contexte utilisateur de repli, et aucune limite de consentement par ressource : une application dotée de Files.ReadWrite.All peut toucher un fichier qui ne lui a jamais été partagé, dans un site avec lequel elle n'a aucune autre relation.

RoleManagement.ReadWrite.Directory appartient à une catégorie plus restreinte, et plus dangereuse encore. La documentation des permissions de Microsoft elle-même signale une classe de « permissions permettant d'accorder une autorisation » — des permissions qui laissent une application distribuer des privilèges supplémentaires à elle-même, à d'autres applications ou à n'importe quel utilisateur — comme nécessitant une prudence particulière (référence des permissions Microsoft Graph). RoleManagement.ReadWrite.Directory est exactement ce type de permission pour les rôles d'annuaire Entra : une application qui la détient peut attribuer n'importe quel rôle Entra intégré, y compris Global Administrator, à n'importe quel principal de sécurité — y compris elle-même.

La chaîne d'attaque : d'un identifiant divulgué à Global Administrator

Il ne s'agit pas d'une composition théorique de deux permissions dangereuses — c'est une technique documentée. Une recherche de Semperis (publiée sous le nom « EntraGoat Scenario 2 ») détaille exactement ce chemin d'escalade de bout en bout.

Étape 1 — Exposition de l'identifiant

Un attaquant récupère un certificat encodé en base64 et un mot de passe laissés dans des artefacts de pipeline CI/CD.

Étape 2 — Attribution

L'empreinte (thumbprint) du certificat est rapprochée des métadonnées keyCredentials.customKeyIdentifier d'un service principal, ce qui identifie à quelle application il appartient.

Étape 3 — Authentification app-only

L'attaquant s'authentifie en tant que service principal via le flux OAuth 2.0 client credentials — aucune invite MFA, aucune stratégie de connexion d'accès conditionnel à satisfaire, car il n'y a tout simplement pas de connexion interactive.

Étape 4 — Reconnaissance

L'attaquant inspecte la revendication roles du token et constate que le service principal détient déjà AppRoleAssignment.ReadWrite.All — une permission qui lui permet d'attribuer des rôles d'application Graph à n'importe quel service principal, y compris lui-même.

Étape 5 — Auto-escalade

Grâce à cette permission, l'attaquant attribue RoleManagement.ReadWrite.Directory au même service principal.

Étape 6 — Attribution de rôle

Avec un nouveau token portant la nouvelle permission, l'attaquant ajoute le service principal au rôle d'annuaire Global Administrator — un appel aussi simple que New-MgDirectoryRoleMemberByRef contre l'ID de modèle de rôle bien connu de Global Administrator (62e90394-69f5-4237-9190-012177145e10).

Étape 7 — Prise de contrôle

Comme les rôles d'annuaire Entra sont évalués dynamiquement à l'exécution plutôt qu'intégrés dans le token, le service principal devient un Global Administrator pleinement privilégié dès son appel suivant — à partir de là, l'attaquant peut réinitialiser le mot de passe de n'importe quel administrateur.

AppRoleAssignment.ReadWrite.All (déjà détenue)
        |
        v
  attribuer RoleManagement.ReadWrite.Directory à soi-même
        |
        v
  ajouter le service principal au rôle Global Administrator
        |
        v
  réinitialiser le mot de passe admin cible -> prise de contrôle totale du tenant

🚨 Danger : l'étape 4 est ce que les défenseurs manquent le plus souvent. Le résultat dangereux ici n'est pas une seule permission sur-privilégiée — c'est la combinaison. AppRoleAssignment.ReadWrite.All seule permet à une application d'accorder des permissions Graph à des service principals ; RoleManagement.ReadWrite.Directory seule permet à une application de gérer les rôles d'annuaire. Aucune revue ne détecte la paire, sauf si quelqu'un recherche spécifiquement les permissions permettant d'accorder des autorisations.

Détection

Concentrez la détection sur le moment où une permission dangereuse est accordée et sur le moment où elle est utilisée pour toucher aux rôles d'annuaire — les deux sont journalisés par défaut dans le journal d'audit Microsoft Entra, sans add-on premium requis.

IndicateurActivité du journal d'auditSur quoi filtrerSource
Application ayant reçu une permission applicative dangereuseAdd app role assignment to service principalTarget(s) = Microsoft Graph, AppRole.Value dans Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All, RoleManagement.ReadWrite.DirectoryJournal d'audit Entra (Catégorie : ApplicationManagement)
Service principal ajouté à un rôle d'annuaire privilégiéAdd member to role, Add eligible member to role, ou Add scoped member to roleType de principal = service principal, rôle = Global Administrator ou un autre rôle privilégiéJournal d'audit Entra
Un admin a approuvé le consentementConsent to applicationConsentContext.IsAdminConsent = trueJournal d'audit Entra
Consentement d'un utilisateur final à un scope risquéConsent to applicationConsentContext.IsAdminConsent = false, l'application demande un scope à haut risqueJournal d'audit Entra

Il s'agit là de la recommandation officielle documentée par Microsoft — voir Opérations de sécurité Microsoft Entra pour les applications, qui fournit également des détections Microsoft Sentinel prêtes à l'emploi pour exactement ce schéma « app role with sensitive access » et pour ServicePrincipalAssignedPrivilegedRole.

Établir une base de référence des attributions existantes

Pour établir une base de référence de ce qui est déjà accordé, interrogez directement les attributions de rôles d'application existantes plutôt que d'attendre le prochain événement d'audit :

# Enumerate service principals holding any of the four dangerous permissions
$dangerousRoleIds = @(
    "19dbc75e-c2e2-444c-a770-ec69d8559fc7", # Directory.ReadWrite.All
    "e2a3a72e-5f79-4c64-b1b1-878b674786c9", # Mail.ReadWrite
    "75359482-378d-4052-8f01-80520e7db3cd", # Files.ReadWrite.All
    "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8"  # RoleManagement.ReadWrite.Directory
)
$graphSp = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $graphSp.Id -All |
    Where-Object { $_.AppRoleId -in $dangerousRoleIds }
ℹ️

ℹ️ Remarque : AppRoleAssignment.ReadWrite.All — la permission qui a rendu possible l'étape 5 de la chaîne d'attaque — mérite d'être auditée séparément, indépendamment des quatre permissions ci-dessus. Tout service principal qui la détient peut s'accorder n'importe quoi d'autre dans ce tableau.

Surveillez également les journaux d'activité Microsoft Graph à la recherche d'un service principal qui se met soudainement à appeler /roleManagement/directory/roleAssignments ou /servicePrincipals/{id}/appRoleAssignedTo — des endpoints qu'une intégration normale (synchronisation de mails, de fichiers, d'annuaire) n'a aucune raison de toucher.

Remédiation

💡

💡 Astuce : exécutez la requête PowerShell ci-dessus dès aujourd'hui. Tout service principal détenant RoleManagement.ReadWrite.Directory qui n'est pas une intégration PIM ou de gouvernance documentée et activement utilisée doit être révoqué immédiatement — cette permission n'a pratiquement aucun usage légitime en dehors des outils de gouvernance des identités.

  1. Classez les quatre permissions comme à fort impact. Dans Entra ID > Enterprise applications > Consent and permissions > Permission classifications, marquez Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All et RoleManagement.ReadWrite.Directory comme high impact afin que les utilisateurs ordinaires ne puissent jamais y consentir, même si le consentement utilisateur est activé par ailleurs (Configurer la façon dont les utilisateurs consentent aux applications).
  2. Routez tout le reste via le workflow de consentement admin. Activez le workflow de consentement admin afin qu'un utilisateur bloqué puisse demander une revue au lieu que la demande disparaisse silencieusement — mais associez-le à l'étape 1, car ce workflow n'a d'importance que si les utilisateurs ne peuvent pas simplement le contourner en s'auto-consentant.
  3. Préférez des permissions plus étroites. Mail.ReadWrite et Files.ReadWrite.All sont fréquemment sur-dimensionnées par rapport à ce que l'intégration fait réellement — une stratégie d'accès aux applications peut restreindre Mail.ReadWrite à des boîtes aux lettres spécifiques plutôt qu'à toutes les boîtes du tenant, et le consentement spécifique à une ressource peut réduire l'accès aux fichiers en deçà de Files.ReadWrite.All.
  4. Traitez l'identifiant comme un secret Tier 0. Chacune de ces permissions n'est jamais plus sûre que le certificat ou le client secret qui la protège — voir Rotation des secrets App Registration Entra pour ce à quoi ressemblent en pratique des secrets « périmés » et « sur-partagés », et ne laissez jamais un secret traîner dans un artefact CI/CD comme le décrit la recherche de Semperis.
  5. Restreignez jusqu'à l'endroit où le service principal peut s'authentifier. L'accès conditionnel pour les identités de workload applique des stratégies de localisation et de risque de connexion sur les authentifications de service principal vers Microsoft Graph, et l'évaluation continue de l'accès pour les identités de workload révoque un token quasiment en temps réel si le signal de risque change en cours de session.
  6. Relancez le rapport des consentements accordés aux applications selon un calendrier régulier, pas uniquement lors de l'onboarding — un audit des consentements accordés fait remonter des permissions que personne ne se souvient d'avoir approuvées, et une permission justifiée il y a deux réorganisations l'est rarement encore.
  7. Intégrez les attributions de rôle des service principals à votre revue des accès privilégiés, aux côtés des attributions PIM humaines — un service principal en Global Administrator est exactement aussi dangereux qu'un Global Admin humain permanent, et CVE-2025-55241 rappelle l'étendue de portée que porte ce seul rôle.

Comment EtcSec détecte cela

L'audit Entra ID d'EtcSec vérifie exactement cette exposition : APP_DANGEROUS_PERMISSION_DIR, APP_DANGEROUS_PERMISSION_MAIL, APP_DANGEROUS_PERMISSION_FILES et APP_DANGEROUS_PERMISSION_ROLE signalent chacune un service principal détenant l'une des quatre permissions ci-dessus, et APP_CONSENT_GRANTED_TENANT_WIDE signale les consentements accordés à l'échelle de tous les utilisateurs du tenant plutôt qu'à un groupe restreint.

ℹ️

ℹ️ Remarque : EtcSec vérifie automatiquement cette vulnérabilité à chaque audit Azure/Entra. Lancez un audit gratuit pour voir lesquelles de vos App Registrations détiennent déjà l'une de ces permissions.