TRR0020: Service Principal Manipulation

2024/01/11

Metadata

KeyValue
IDTRR0020
External IDsAZT501.2, T1098.001, T1098.003
TacticsPersistence
PlatformsAzure
ContributorsAndrew VanVleet

Scope Statement

This TRR covers manipulation of a service principle for persistence in Azure, which corresponds to multiple subtechniques on the Mitre ATT&CK matrix and Microsoft’s Azure Threat Research Matrix (ATRM). The following techniques are addressed, as they pertain to Azure:

Technique Overview

Attackers can use Azure service principals to achieve persistent access to a compromised tenant. Those options include:

  1. Adding new credentials to an existing service principal (T1098.001 & AZT501.2)
  2. Adding an account they control as a new owner of a service principal. (AZT501.2)
  3. Granting a service principal they control additional roles. (T1098.003)
  4. Granting a service principal additional permissions.

Technical Background

Security Principals

To access resources that are secured by a Microsoft Entra tenant, the entity that requires access must be represented by a security principal. This requirement is true for both users (user principal) and applications (service principal). The security principal defines the access policy and permissions for the user/application in the Microsoft Entra tenant.

There are three types of service principal:

Applications

Applications in Azure have two components:

  1. An App Registration
  2. A Service Principal (aka Enterprise Application)

An App Registration is how you register a new application with Azure; it is the global representation of your application in Azure across all tenants and is assigned a globally unique application object ID. You can configure details like the reply and logout URLs, define the application’s APIs, and add credentials for your application to use to authenticate. You also define the specific permissions that your application will need to use various Azure resources.

A Service Principal is the local representation of an application in a single tenant only. A service principal is created in each tenant where the application is used and references the globally unique app object. The service principal object defines what the app can actually do in the specific tenant, who can access the app, and what resources the app can access. When an application is given permission to access resources in a tenant (upon registration or consent), a service principal object is created.

An example helps illustrate this concept: ZScaler offers a “Private Access” (ZPA) product in Azure. The App Registration for ZPA exists in ZScaler’s own tenant. If you want to use the application in your tenant, you go to Enterprise Applications, create a new application, and select ZPA from the “Azure AD Gallery.” This will create a service principle for ZPA in your tenant and you will need to grant your consent for it to hold the application permissions that it requires (which were defined by ZScaler in the App Registration). You can then use ZPA in your tenant.

Azure Roles and Permissions

Azure permissions are assigned to principals using role-based access control (RBAC). There are two distinct RBAC systems operating inside an Azure tenant. All resources in Azure will be controlled by one or the other of these two RBAC systems. Roles for both RBAC systems can be assigned to any user, group, or service principal.

In the Azure portal, you can see these permissions in different blades (see image) on the profile for a user, group, or service principal.

Image showing Entra and Azure roles in the portal

Entra ID RBAC (formerly Azure AD)

Entra ID roles apply to directory resources like users, groups, domains, applications, licenses, synchronization settings, etc. Entra offers many built-in roles, plus the ability to create custom roles. At its core, a role assignment consists of three elements:

Microsoft Entra ID provides multiple options for assigning roles:

Global Administrator is the most well-known built-in Entra ID role; this role is at the top of the Entra ID hierarchy. A Global Administrator in Entra can elevate themselves to the Azure RBAC User Access Administrator role over the tenant’s root management group (which is the top of the Azure RBAC hierarchy), allowing them to grant themselves access to any resource in the tenant.

Azure RBAC

Azure RBAC defines roles with common access needs that can be assigned to principals. Principals include users, security groups, managed identities, workload identities, and service principals. (Principals are created and managed in Entra.) You can assign a role to any principal. There are over 70 built-in roles, and it’s possible to define custom ones. However, there are 4 fundamental roles that apply to all resources:

RolePermissions
OwnerFull access to all resources and manage access for other users
ContributorFull access to all resources
ReaderView all resources
User Access AdministratorView all resources and manage access for other users

Azure roles are always scoped to a specific resource. In the Azure Portal, they are accessed by selecting a resource and choosing the “Access Control (IAM)” blade. There you can see the roles defined for the resource and the principles (users, assignable groups, and applications) who are assigned those roles. Because permissions are inherited from parent resource groups and subscriptions, the highest level of access in Azure RBAC is Owner or User Access Administrator on the Root Management Group (the latter can grant themselves the former). However, the Entra ID Global Administrator role can grant itself the Owner role on any resource, so it also controls the whole tenant. Likewise, any account with the control plane action Microsoft.Authorization/*/Write (which is held by the User Access Administrator) could grant themselves permissions to any resource within the scope where the permission is granted.

Each Azure role defines a set of permissions that are granted or denied to the role. These are listed as Actions and NotActions. You can see a role definition with AZ Powershell by using the cmdlet get-azroledefinition. Azure separates permissions for control plane actions from data plane actions. Control plane actions are things like managing access to a storage account, or creating a blob container, key vault, or resource group. Data plane actions are things like reading or writing blobs in a container or reading a key in a key vault.

By way of example, here is the definition for the role Storage Blob Data Reader, which has rights to both read the containers (control plane), and also to read the blobs inside the container (data plane):

{  
  "Name": "Storage Blob Data Reader",  
  "Id": "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1",  
  "IsCustom": false,  
  "Description": "Allows for read access to Azure Storage blob containers and data",  
  "Actions": [
   "Microsoft.Storage/storageAccounts/blobServices/containers/read", 
   "Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action"
  ],  
  "NotActions": [],  
  "DataActions": [
    "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read"
  ],
  "NotDataActions": [],  
  "AssignableScopes": [    
   "/"  
  ]
}

Procedures

IDTitleTactic
TRR0020.AZR.AAdd credentialsPersistence
TRR0020.AZR.BAdd ownerPersistence
TRR0020.AZR.CAdd rolePersistence
TRR0020.AZR.DAdd API permissionsPersistence

Procedure A: Add credentials

An attacker can gain persistence in a compromised Azure tenant by adding new credentials to a service principal with the permissions the attacker is interested in retaining. Adding credentials known by the attacker would allow them to authenticate as that service principal until those credentials are revoked.

Credentials can be certificates, client secrets (a string), or federated identity credentials.

Adding Credentials via the Azure Portal

Detection Data Model

DDM - Add credentials

Adding credentials to a service principal name (SPN) as a user requires a role with the Microsoft.Directory/servicePrincipals/credentials/update permission in Entra. To add credentials as an application, one of the Application.ReadWrite* Graph permissions is required. There are many options for how to do it, including Powershell (New-AzAdSpcredential), the Graph API6, or the Azure portal. There is one relevant Entra Audit log generated: “Update Application - Certificates and secrets management.”

Procedure B: Add owner

An attacker can establish persistence by adding themselves as an owner to an existing application. They can be owners of both the service principal or the application registration.

Image of adding owner in Azure portal

An attacker is most likely to add themselves as an additional owner of an application that already holds permissions they want in the tenant, but as an owner they can also add new permissions to any application (though admin consent would be required). They can also manage the tenant-specific configuration of the application, such as the single sign-on (SSO) configuration.

Ownership grants an adversary permissions to carry out other account manipulation procedures, like adding roles, permissions, or credentials. Some of the permissions held by owners over an application registration that would be useful to an attacker are:

ActionDescription
microsoft.directory/applications/authentication/updateUpdate the applications.authentication property in Microsoft Entra ID.
microsoft.directory/applications/credentials/updateUpdate the applications.credentials property in Microsoft Entra ID.
microsoft.directory/applications/permissions/updateUpdate the applications.permissions property in Microsoft Entra ID.
microsoft.directory/applications/policies/updateUpdate the applications.policies property in Microsoft Entra ID.

Similarly, attackers would find the following permissions held by owners of enterprise applications useful:

ActionDescription
microsoft.directory/policies/deleteDelete policies in Microsoft Entra ID.
microsoft.directory/servicePrincipals/appRoleAssignments/updateUpdate the users.appRoleAssignments property in Microsoft Entra ID.
microsoft.directory/servicePrincipals/authentication/updateUpdate the servicePrincipals.authentication property in Microsoft Entra ID.
microsoft.directory/servicePrincipals/credentials/updateUpdate the servicePrincipals.credentials property in Microsoft Entra ID.

Detection Data Model

DDM - Add owner

Adding an owner to an SPN or application requires a role with the Microsoft.Directory/servicePrincipals/owners/update or Microsoft.Directory/applications/owners/update permissions in Entra. To add an owner as an application, one of the Application.ReadWrite* Graph permissions is required. There are many options for how to do it, including the AZ command line interface78, the Graph API9, or the Azure portal. There are two Entra Audit logs generated: “Add owner to application” or “Add owner to service principal.”

Procedure C: Add role

Attackers can establish persistence by granting additional privileged roles to an attacker-controlled service principal. These roles could be assigned in both Entra or Azure RBAC.

Image of Menu to Add Azure Role Assignment in Entra

Privileged Roles

Privileged roles are those that grant administrative access, such as the ability to manage Azure resources or assign roles to other users. The following Azure roles are considered privileged and apply to all resource types.

Azure rolePermissions
OwnerGrants full access to manage all resources, assign roles in Azure RBAC
ContributorGrants full access to manage all resources, can’t assign roles in Azure RBAC. Can’t manage assignments in Azure Blueprints or share image galleries.
Reservations AdministratorManage all the reservations in a tenant. Assign roles in Azure RBAC for reservations
Role Based Access Control AdministratorManage user access to Azure resources. Assign roles in Azure RBAC. Assign themselves or others the Owner role. Can’t manage access using other ways, such as Azure Policy
User Access AdministratorManage user access to Azure resources. Assign roles in Azure RBAC. Assign themselves or others the Owner role

These specific Azure permissions are considered privileged, regardless of the role holding them:

Action stringDescription
*Create and manage resources of all types.
*/deleteDelete resources of all types.
*/writeWrite resources of all types.
Microsoft.Authorization/denyAssignments/deleteDelete a deny assignment at the specified scope.
Microsoft.Authorization/denyAssignments/writeCreate a deny assignment at the specified scope.
Microsoft.Authorization/roleAssignments/deleteDelete a role assignment at the specified scope.
Microsoft.Authorization/roleAssignments/writeCreate a role assignment at the specified scope.
Microsoft.Authorization/roleDefinitions/deleteDelete the specified custom role definition.
Microsoft.Authorization/roleDefinitions/writeCreate or update a custom role definition with specified permissions and assignable scopes.

Detection Data Model

DDM - Add role

Changes to Entra ID objects, including adding or removing roles, are logged in the Azure Audit Log. The Entra logs that are most relevant to this technique are:

Operation NameDescription
Add member to groupAdd a user, group, or service principal to a group (and all the roles the group holds)
Add member to role
Add eligible member to role
Add a user, group, or service principal to a role (either permanently or temporarily)
Add eligible member to role in PIM completed (permanent)
Add eligible member to role in PIM completed (time bound)
Add eligible member to role in PIM requested (permanent)
Add eligible member to role in PIM requested (time bound)
Add member to role approval requested (PIM activation)
Add member to role completed (PIM activation)
Add member to role in PIM completed (permanent)
Add member to role in PIM completed (time bound)
Add member to role in PIM requested (permanent)
Add member to role in PIM requested (time bound)
Add member to role outside of PIM (permanent)
Add member to role request approved (PIM activation)
Add member to role request denied (PIM activation)
Add member to role requested (PIM activation)
Various logs for assigning users to roles via PIM (which can assign either temporarily or permanently)
Add role definition
Update role definition
Add or modify the permissions for a custom role definition.

Changes to Azure resources, including adding or removing roles, are logged in the Azure Activity Log. These are the RBAC-related operations that get logged (under the Category “Administrative” with the operationName “Authorization”):

PermissionDescription
Microsoft.Authorization/roleAssignments/writeCreate role assignment
Microsoft.Authorization/roleAssignments/deleteDelete role assignment
Microsoft.Authorization/roleDefinitions/writeCreate or update role definition
Microsoft.Authorization/roleDefinitions/deleteDelete role definition

Procedure D: Add API permissions

An attacker can establish persistence by granting additional API permissions to an application they control. Changes to an application’s permissions must be approved through consent.

Granting Permissions to Applications

Applications request specific permissions in the tenant and must be granted these by user or admin consent. Each permission includes a claim (User.Read, User.Write, etc) against an API (Microsoft Graph, Azure Resource Management, Windows Azure Active Directory, etc).

There are two scopes for which a permission can be requested: Application and Delegated.

Application Permissions

Application permissions are used by apps that run without a signed-in user present, for example, apps that run as background services. These permissions are held directly by the application and apply to all relevant resources in the tenant. For example, an app that has the Mail.Read permission can read the mailboxes of every user in the organization.

Delegated Permissions

Delegated permissions are used by apps that have a signed-in user present. They grant the application the ability to exercise the requested permission on behalf of the user. The app is delegated with the permission to act as a signed-in user when it makes calls to the target resource. For example, an app with a Mail.Read delegated permission can read the mailbox of the signed-in user only.

For delegated permissions, the effective permissions of your app are the least-privileged intersection of the delegated permissions the app has been granted (by consent) and the privileges of the currently signed-in user. Your app can never have more privileges than the signed-in user. For example, if a signed-in user doesn’t have rights to read their own mailbox, then an application with the Mail.Read delegated permission will not have permission to read the user’s mailbox.

Application Permissions in Azure Portal

Consent is a process where users or admins authorize an application to access a protected resource. Consent can be granted by individual users for their own data (delegated) or by an administrator for tenant-wide permissions (application or delegated).

User consent happens when a user attempts to sign in to an application and grants that application delegated permissions to access specific resources as the user. The user provides their sign-in credentials, which are checked to determine if consent has already been granted for the requested permissions. If no previous record of user or admin consent for the permissions exists, the user is shown a consent prompt and asked to grant the application the requested permissions. For specific permissions, an admin may be required to grant consent on behalf of the user. Once a user has consented to delegated permissions for an application, they don’t have to grant it again for the same application.

Administrators can grant consent for delegated permissions for specific users or for an entire organization. Applications can also be pre-authorized for permissions so that users don’t see a consent prompt when they first use the application. Application permissions can only be granted by admin consent. Additionally, depending on the permissions they require, some applications might require an administrator to be the one who grants consent, even for a single user. For example, many high-privilege delegated permissions can only be consented to by an administrator (see Risky Graph Permissions below). Authentication requests are prompted for admin consent if consent wasn’t granted and if one of those high-privilege permissions is requested. Global Admin, Privileged Role Admins, Application Admin, and Cloud Application Admins all have permission to grant tenant-wide consent (but only the first two can consent to Graph API permissions)10. Additionally, custom roles that hold the permission microsoft.directory/servicePrincipals/managePermissionGrantsForAll can grant admin consent.11

Image of Azure portal showing consent required for new permission

Generally, granting permissions to an application within a tenant always requires that consent be granted by a human admin. There is one method that allows consent to be bypassed: an application holding the AppRoleAssignment.ReadWrite.All can grant itself or any other application any application permission to any API, including Microsoft Graph, without the normally required admin consent process. By way of example, an application with this permission could escalate to Global Admin without consent by granting itself RoleManagement.ReadWrite.Directory and Global Admin, in turn.12

Risky Graph Permissions

The following Graph permissions are more likely to be targeted by attackers because they permit access to files, contacts, notes, mail, or the ability to make sensitive changes to permissions. The addition of these permissions to an application or role – or the addition of a role containing these permissions – would be interesting from a security perspective. The full list of Graph permissions and whether they require admin consent can be found in the Graph Permissions Reference.13

Detection Data Model

DDM - Add API permissions

To add a new API permission, there are two options: via consent or bypassing consent. The permissions required differ per approach. When a new permission is added, Entra logs an Update Application log with a change to the RequiredResourceAccess field (this is the section that declares the permissions required for an application). When consent is granted, there is a Consent to application and Add app role assignment to service principal log generated.

The DDM focuses on application permissions rather than delegated permissions because to abuse delegated permissions an attacker must be able to sign a user in to the application in order to access their data, including passing all MFA and Conditional Access checks, even after they’ve granted and consented to the permission in Entra. This makes application permissions considerably easier to abuse. In Azure logging, delegated permissions are called an OAuth2PermissionGrant and application permissions are called an appRoleAssignment.

Available Emulation Tests

IDLink
TRR0020.AZR.AAtomic Test 1, Atomic Test 2
TRR0020.AZR.B
TRR0020.AZR.CAtomic Test 1-2, Atomic Test 5, Atomic Test 7
TRR0020.AZR.DAtomic Test 8

References


  1. Entra Managed Identities - Microsoft Learn ↩︎

  2. Application and service principal objects in Microsoft Entra ID - Microsoft Learn ↩︎

  3. Azure Resource Manager - Microsoft Learn ↩︎

  4. Access Token Request with a Federated Credential - Microsoft Learn ↩︎

  5. Adding Credentials - Microsoft Learn ↩︎

  6. Graph API ServicePrincipal Add Password - Microsoft Learn ↩︎

  7. AZ CLI App Owner - Microsoft Learn ↩︎

  8. AZ CLI SPN Owner - Microsoft Learn ↩︎

  9. Graph API ServicePrincipal Add Owner - Microsoft Learn ↩︎

  10. Microsoft Entra built-in roles - Microsoft Learn ↩︎

  11. App consent permissions for custom roles - Microsoft Learn ↩︎

  12. Azure Privilege Escalation via API Permissions Abuse - SpecterOps ↩︎

  13. Microsoft Graph Permissions Reference - Microsoft Learn ↩︎