This change was detected by Azure AD Role Monitor because it is possible to abuse this action to escalate privileges or move laterally within a tenant.
In this case, the addition of this action to the role Hybrid Identity Administrator does not add any additional security risk to principals that are assigned this role, because the role has other privileged actions that supersede these privileges and which may be abused to reach the same result. However, it raises the question – how can this action be abused, and what does it give you access to?
In this post, I briefly explore what the action allows a principal to do within an Entra ID tenant, and describe an example scenario of how it could be abused to gain additional privileges.
Entra ID administrative roles
Before we dive into the appRoleAssignedTo action, it is important to understand what an action is, and how it relates to an Entra ID role and tenant. To understand this, let’s take a look at what Entra ID roles are¸ and how they are defined.
The basics
An Entra ID tenant is the logical entity that represents one organization’s instance of Entra ID. So, a tenant can be seen as a scope of objects that contain the groups, applications, users, and directory settings for one company.
To administer the objects in a tenant, Microsoft provides Entra ID customers with the ability to assign administrative permissions to principals within their tenant. These permissions can allow a principal to create, delete, read and modify objects and configurations in the tenant. However, it is rarely necessary for a principal to have administrative access to all settings and objects in a directory, and if all users are assigned administrative access to the entire tenant this poses a security risk to the organization.
To help reduce privileges assigned in a tenant, Microsoft supports Role-Based Access Control(RBAC) within Entra ID. Note that RBAC in Entra ID should not be confused with Azure RBAC, which is the name of the RBAC permission model for Azure Resources. In Entra ID, RBAC provides a way for a principal to be assigned a limited administrative role that only has access to a subset of functionality within the tenant. Commonly used examples include User Administrator and Group Administrator.
But how do we know what each built-in role is able to do within Entra ID? This is where things get interesting, because it is not possible to understand this based solely on the role name and descriptor.
Entra ID role definitions
A role definition is in fact further broken down into a set of specific permissions within Entra ID, which Microsoft calls “actions”. So with the example of a User Administrator role, the role can be described using the following actions, which can be retrieved directly from the Microsoft Graph API:
"rolePermissions": [ { "allowedResourceActions": [ "microsoft.directory/accessReviews/definitions.applications/allProperties/allTasks", "microsoft.directory/accessReviews/definitions.directoryRoles/allProperties/read", "microsoft.directory/accessReviews/definitions.entitlementManagement/allProperties/allTasks", "microsoft.directory/accessReviews/definitions.groups/allProperties/update", "microsoft.directory/accessReviews/definitions.groups/create", "microsoft.directory/accessReviews/definitions.groups/delete", "microsoft.directory/accessReviews/definitions.groups/allProperties/read", "microsoft.directory/contacts/create", "microsoft.directory/contacts/delete", "microsoft.directory/contacts/basic/update", "microsoft.directory/deletedItems.groups/restore", "microsoft.directory/deletedItems.users/restore", "microsoft.directory/entitlementManagement/allProperties/allTasks", "microsoft.directory/groups/assignLicense", "microsoft.directory/groups/create", "microsoft.directory/groups/delete", "microsoft.directory/groups/hiddenMembers/read", "microsoft.directory/groups/reprocessLicenseAssignment", "microsoft.directory/groups/restore", "microsoft.directory/groups/basic/update", "microsoft.directory/groups/classification/update", "microsoft.directory/groups/dynamicMembershipRule/update", "microsoft.directory/groups/groupType/update", "microsoft.directory/groups/members/update", "microsoft.directory/groups/onPremWriteBack/update", "microsoft.directory/groups/owners/update", "microsoft.directory/groups/settings/update", "microsoft.directory/groups/visibility/update", "microsoft.directory/oAuth2PermissionGrants/allProperties/allTasks", "microsoft.directory/policies/standard/read", "microsoft.directory/servicePrincipals/appRoleAssignedTo/update", "microsoft.directory/users/assignLicense", "microsoft.directory/users/create", "microsoft.directory/users/delete", "microsoft.directory/users/disable", "microsoft.directory/users/enable", "microsoft.directory/users/inviteGuest", "microsoft.directory/users/invalidateAllRefreshTokens", "microsoft.directory/users/reprocessLicenseAssignment", "microsoft.directory/users/restore", "microsoft.directory/users/basic/update", "microsoft.directory/users/manager/update", "microsoft.directory/users/password/update", "microsoft.directory/users/photo/update", "microsoft.directory/users/sponsors/update", "microsoft.directory/users/usageLocation/update", "microsoft.directory/users/userPrincipalName/update", "microsoft.azure.serviceHealth/allEntities/allTasks", "microsoft.azure.supportTickets/allEntities/allTasks", "microsoft.office365.serviceHealth/allEntities/allTasks", "microsoft.office365.supportTickets/allEntities/allTasks", "microsoft.office365.webPortal/allEntities/standard/read" ], "condition": null } ], "inheritsPermissionsFrom@odata.context": "https://graph.microsoft.com/beta/$metadata#roleManagement/directory/roleDefinitions('fe930be7-5e62-47db-91af-98c3a49a38b1')/inheritsPermissionsFrom", "inheritsPermissionsFrom": [ { "id": "88d8e3e3-8f55-4a1e-953a-9b9898b8876b" } ] |
The action names are more descriptive than the role name, and include some surprises. For example, you may not know that a user assigned to the User Administrator role would also be able to manage Entra ID Groups and Access Reviews.
These actions are individually described by Microsoft at https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference. However, even with these descriptions, it is not always clear what security impact a specific action has. To truly understand this, we need to know what specific permissions an action provides within Entra ID and the Microsoft Graph API.
The following diagram shows at a high level the relationship between this data in Entra ID:
The microsoft.directory/servicePrincipals/ appRoleAssignedTo/update permission
One action that may be particularly confusing to some is the subject of this article: the microsoft.directory/servicePrincipals/ appRoleAssignedTo/update action. Microsoft states the following description about this action:
“Update service principal role assignments”
This isn’t very descriptive, and could mean a few things in Entra ID.
After some testing, I identified that this action provides a user with the ability to create and modify App Role Assignments on applications that integrate with the Microsoft Identity Platform for SSO.
Make sense?
Probably not, and what is an App Role? And is it possible to abuse this permission?
App Roles
App roles are very central to how developers integrate with Entra ID for Authorization to their applications. In order to understand this, I recommend understanding OAuth2 and JWT tokens.
When developers want to use Entra ID as an identity provider to provide single sign on for their application using Microsoft or other social accounts, they need to integrate with the Microsoft Identity Platform. The Microsoft Identity Platform is essentially Microsoft’s implementation of OAuth2, where Entra ID is the management interface for creating and managing OAuth Clients and Resources.
An App Role is built-in functionality in the Microsoft Identity Platform that defines a specific “role” for users in an application. For example, a user might have the “administrator” role, the “user” role, or the “operator” role in a SaaS application. To implement this, a developer can “register” an application within Entra ID that acts as an OAuth2 Resource Server, and define the “roles” that will be available within that application using Entra ID settings on the application. In the Azure portal, this is the following functionality:
When a principal performs an OAuth2 flow using the Microsoft Identity Platform to get a token for this resource, they will be issued a “roles” claim in the access token issued to their user. Developers on the SaaS application must then use the roles claim to determine what roles an individual user has on the application.
So, who can add users to the administrator role on this application?
Back to the microsoft.directory/servicePrincipals/ appRoleAssignedTo/update
action. If a principal or user is assigned a role that has this action, they may assign users to arbitrary roles on an application. This capability can be found in the portal on the “Enterprise Application” blade that represents the Service Principal for the above application:
So in recap, microsoft.directory/servicePrincipals/ appRoleAssignedTo/update allows a principal to create role assignments on SaaS applications that are federated through Azure AD.
Abuse impact
So what is the impact of an adversary abusing this action?
It depends on tenant configurations and which applications have been federated through Azure AD. However, some potential impacts might include:
- AWS tenant lateral movement and privilege escalation
- Azure AD tenant privilege escalation
- SaaS application administrative takeover
The AWS abuse technique is possible because of the old way of federating access to AWS through Entra ID, which utilized App Roles to provide access to the cloud provider management planes.
However, there are occasionally more convoluted, or “bespoke”, if you will, privilege escalations that can be identified in a tenant. These are entirely dependent on the Azure AD permissions and functionality of the federated SaaS applications. Let’s dive into an example scenario.
Privilege Escalation via SaaS abuse
The following example is a very simple scenario where an External SaaS application may be abused using the microsoft.directory/servicePrincipals/ appRoleAssignedTo/update action to escalate privileges in a tenant. Note that this is a simple example that requires no application-level attacks, but there are an infinite number of possible scenarios when you consider that application-level vulnerabilities may also allow the abuse of a SaaS app after a user gives themselves some level of access. This is a very interesting intersection between the fields of application security testing and cloud security testing.
Setup
In our scenario, cloud-based identity governance and administration(IGA) tool called IGAPro has built the Authorization layer of their product on the Microsoft Identity Platform. The IGA tool federates access to the application through a customer’s Azure AD tenant.
The IGAPro requires the following application permissions against Microsoft Graph:
- Groups.ReadWrite.All
- Users.ReadWrite.All
A company called weboxo has decided to utilize IGAPro in their tenant, and has consented to these application permissions on the service principal for IGAPro:
IGA Pro exposes two roles: reader and admin:
Weboxo also uses role-assignable groups to manage all Entra ID role assignments, so all Entra ID roles have an assigned role-assignable group. For increased security, weboxo also uses Entra ID PIM for groups functionality to provide access to these role-assignable groups on a just-in-time basis. Members of the tenantAdministrator group are eligible to become members of these role groups.
Adverary scenario
In this scenario, an adversary has compromised a user that has been assigned the Directory Writers role, which contain the microsoft.directory/servicePrincipals/ appRoleAssignedTo/update action.
Abusable IGAPro Functionality
IGAPro offers the ability to directly modify group memberships in Azure AD.
Visual of attack path
The following diagram depicts how a compromised directory writer may abuse the microsoft.directory/servicePrincipals/ appRoleAssignedTo/update action to exploit our scenario to become Global Administrator:
Mitigations and detection
The best course of action for mitigating the abuse technique is to identify and monitor attack paths in an Entra ID tenant on a consistent basis, and limit these attack paths using architectural designs such as a proper tiering strategy. Azure AD Role monitor provides a list of known primitives on all Azure AD roles, and is updated nightly to ensure new changes are captured. Considering using this data to define a tiering strategy that limits the exposure of dangerous roles, such as those than contain the microsoft.directory/servicePrincipals/ appRoleAssignedTo/update action.
In addition, it is important to maintain an inventory of SaaS applications that pose high risk to the business in the event of a compromise, due to either business or technical implications. After establishing this inventory, consider implementing targeted detection rules on new app role assignments against these critical applications. The abuse of this action requires that an attacker updates a role assignment on a service principal for an OAuth Resource in Entra ID. These events can be captured in Entra ID Audit Logs, at the following event types, depending on the type of principal added:
Azure AD Audit Log Category | Activity Name |
UserManagement | Add app role assignment grant to user |
GroupManagement | Add app role assignment grant to group |
ApplicationManagement | Add app role assignment grant to Service Principal |