Skip to content

This tool is not affiliated with, endorsed by or sponsored by Microsoft Corporation. Azure, Microsoft Azure and Microsoft Defender for Cloud are trademarks of the Microsoft group of companies. Other names are trademarks of their respective owners.

Azure role assignment abuse and elevateAccess, investigated

How attackers escalate with Azure role assignments and elevateAccess, what roleAssignments/write events look like in the Activity Log, and how to triage them.

Published on 6 min read

TL;DR. Privilege escalation in Azure is mostly one operation: Microsoft.Authorization/roleAssignments/write. What makes it suspicious is the role (Owner, User Access Administrator, Role Based Access Control Administrator, or Contributor granted to a non-human identity), the caller (a service principal, or a principal assigning a role to itself) and the scope (subscription or root). The nuclear version is Microsoft.Authorization/elevateAccess/action: a Global Administrator gives themselves User Access Administrator at root scope /, over every subscription. That event is written to the tenant-level log, so a subscription export will not show it.

Role assignments are the backbone of Azure authorization, and therefore the first thing an intruder with some access tries to extend. They are also routine administration, which is why a raw list of roleAssignments/write events is useless. This article is about telling the two apart.

How Azure RBAC escalation works

A role assignment binds three things: a principal, a role definition and a scope. Anyone holding Microsoft.Authorization/roleAssignments/write at a scope can create assignments at that scope. In the built-in roles, that means Owner, User Access Administrator and Role Based Access Control Administrator.

Typical escalation paths I see:

Starting pointEscalationWhy it works
Leaked secret of a CI/CD service principal that was given User Access Administrator "to deploy role assignments"Grants itself Contributor or Owner on the subscriptionOver-privileged automation
Compromised Global Administrator in Entra IDelevateAccess → User Access Administrator at / → Owner on any subscriptionEntra and Azure RBAC are separate, but Global Administrators can bridge them
Contributor on a Key Vault using access policiesAdds itself to the vault's access policyNot RBAC, but the same idea — see the Key Vault article
Owner of an Automation account or VM with a privileged managed identityRuns code as that identityCovered in managed identity abuse

MITRE ATT&CK tracks the grant as T1098.003 Additional Cloud Roles and the use of legitimate cloud identities as T1078.004 Cloud Accounts.

What elevateAccess is, and where it is logged

Elevate access is a documented, legitimate feature: a Global Administrator in Microsoft Entra ID can flip "Access management for Azure resources" and receive the User Access Administrator role at root scope /. From there they can assign themselves any role in any subscription and management group of the tenant. Microsoft recommends removing that access once the task is done (Elevate access to manage all Azure subscriptions).

The forensic trap is where it is logged. Per the same page, elevate-access entries appear in the Microsoft Entra directory audit logs (service "Azure RBAC (Elevated Access)", in preview at the time of writing) and in the Directory Activity view of the Activity Log — the tenant-level log. The operation is Microsoft.Authorization/elevateAccess/action with scope /providers/Microsoft.Authorization. A per-subscription az monitor activity-log list does not return it. Export the tenant level with az rest as shown in the export guide.

This is not an exotic path. Microsoft's write-up of Storm-0501 describes the actor using elevateAccess/action to obtain User Access Administrator and then roleAssignments/write to take Owner across subscriptions.

Reading a roleAssignments/write event

In the REST / CLI schema, the details you need are split between the event and its request body:

FieldWhereWhy it matters
caller and claimsEventWho created the assignment. A GUID caller with an appid claim is a service principal; an xms_mirid claim means a managed identity
httpRequest.clientIpAddressEventWhere the call came from
properties.requestbody → PrincipalId, RoleDefinitionId, ScopeRequest bodyWho received which role, where
authorization.evidence.roleResource-log schemaWhich role allowed the caller to do it
status.valueEventStarted / Succeeded / Failed — failures are interesting too

RoleDefinitionId is a GUID. The built-in role IDs are fixed and documented in Azure built-in roles; for example Owner is 8e3af657-a8ff-443c-a75c-2fe8c4bcb635, Contributor b24988ac-6180-42a0-ab88-20f7382dd24c and User Access Administrator 18d7d88d-d35e-4fb5-a5c3-7773c20a72d9.

Two cheap but strong signals:

  1. The caller assigns a role to itself. Compare the caller's object ID with PrincipalId in the request body. Legitimate bootstrap scripts do this occasionally; attackers do it constantly.
  2. The assignee is non-human and the role is broad. A service principal or managed identity receiving Owner or Contributor on a whole subscription deserves an owner and a ticket number.

What the analyzer flags

The Azure Forensics analyzer implements four RBAC rules, all on the Activity Log:

RuleDetectsLevel
AZ-RBAC-001Owner, User Access Administrator or Role Based Access Control Administrator assignedMedium
AZ-RBAC-002Service principal or managed identity assigned Owner, Contributor or an access-management roleHigh
AZ-RBAC-003Principal granted a role to itself (caller object ID = assignee)High
AZ-RBAC-004elevateAccess/action — Global Administrator elevated to root scopeHigh

Pair them with AZ-ID-001 (service principal used from a new IP) and the chain usually reads itself: new IP → self-assignment → whatever came next.

Triage checklist

For every flagged assignment:

  1. Is there a change ticket? Ask the platform team before assuming anything; many "suspicious" assignments are Friday-evening fixes.
  2. Who is the caller, and is this their normal behaviour? Pivot on the caller in the Entities tab. A deployment SP that has never assigned roles before is a strong signal.
  3. From which IP? Compare with the caller's baseline IPs. CI runners change IP; attackers change IP and timing.
  4. What happened next with the new rights? Look at the next hour of events by the assignee. A role nobody uses is a mistake; a role used within minutes to run commands or read secrets is an attack.
  5. Was it removed? Attackers sometimes clean up with roleAssignments/delete. The deletion is also logged.
  6. For elevateAccess: which Global Administrator, from which sign-in? That is an Entra ID question for m365forensics.com.

Remediation

  • Remove assignments created during the incident (az role assignment delete), and review who holds Owner and User Access Administrator at every scope.
  • Remove the User Access Administrator assignment at / created by elevate access; Microsoft documents both the portal toggle and the CLI / REST removal.
  • Rotate the credentials of any service principal that made or received a suspicious assignment.
  • Reduce standing privilege: no User Access Administrator on CI/CD identities; consider Privileged Identity Management for humans.

Related articles

How attackers abuse Azure service principals and managed identities: leaked secrets, IMDS token theft, federated credentials, runbooks, and the log signals.
How attackers use Azure VM Run Command and the Custom Script Extension, what the Activity Log records (and omits), and which on-VM artifacts hold the script.
Think your Azure subscription is compromised? Which logs to preserve first, the operations that betray an attacker, and how to go from Activity Log to verdict.

This tool is not affiliated with, endorsed by or sponsored by Microsoft Corporation. Azure, Microsoft Azure and Microsoft Defender for Cloud are trademarks of the Microsoft group of companies. Other names are trademarks of their respective owners.