Even the most carefully managed Microsoft 365 tenant can be compromised by a single overly-powerful role. This story highlights how a simple test account escalated to Global Administrator and what you can do to prevent it. In this blog, I will walk through a real-world scenario, show how the escalation happened, and explain step by step how to audit, contain, and harden your Microsoft 365 environment against similar risks.
Unexpected Admin Privileges in Microsoft 365
While reviewing Microsoft 365 directory roles, I noticed a test account had suddenly acquired multiple administrative privileges.
There was no official Global Administrator assigned, yet this account could access Exchange Online, SharePoint, Teams, and Security settings. Something didn’t add up.
How to Audit Role Changes with Microsoft Graph PowerShell
To investigate, I used the Microsoft Graph PowerShell SDK to track role assignments. This allowed us to see who added roles and when. Simply use the script below, replacing userPrincipalName
with the email of the user you want to investigate. By filtering for the activity "Add member to role"
and extracting the target user’s UPN along with the timestamp and activity name, it produces a clear, read-only report showing exactly when this action occurred.
Connect-MgGraph -Scopes AuditLog.Read.All, Directory.Read.All
Get-MgAuditLogDirectoryAudit ` -Filter "activityDisplayName eq 'Add member to role' and targetResources/any(t:t/userPrincipalName eq 'testuser@contoso.onmicrosoft.com')" -All | Select-Object ` ActivityDateTime, ActivityDisplayName, @{Name='TargetUser';Expression={ ($_.targetResources | Where-Object {$_.userPrincipalName}) | ForEach-Object {$_.userPrincipalName} }}
Result:
The results were eye-opening: the actor and the target were the same account. In other words, the user had granted administrative roles to itself.
This wasn’t a hack or an external breach—it was an internal privilege escalation made possible by an overlooked role assignment.
Understanding the Root Cause: Privileged Role Administrator
The root cause was the Privileged Role Administrator (PRA) role. This role is extremely powerful because it can:
- Assign any Entra ID role, including Global Administrator
- Grant critical roles like Security Administrator or User Administrator
- Bypass most security guardrails if over-assigned
Think of PRA as the keys to your Microsoft 365 tenant. Mismanagement can allow even a test account to escalate privileges unnoticed.
Why PRA Requires Extra Caution
Many organizations underestimate the power of the PRA role. A few common pitfalls include:
- Over-provisioning – Assigning PRA to too many users, including service accounts or temporary employees.
- Lack of auditing – Not monitoring who holds PRA or when privileges are activated.
- Absence of controls – Missing approval workflows or conditional access restrictions.
These gaps are a recipe for privilege misuse—even unintentionally.
Removing Excess Privileges Safely Using PowerShell
We first removed PRA from the test account, then reviewed all current PRA holders. Only break-glass accounts were allowed to retain PRA.
Use the script below to perform a PowerShell dry-run, safely validating the removal process before making any changes. It first retrieves the Privileged Role Administrator (PRA) role and then lists all its members.
For each member, it checks whether their UserPrincipalName
is not one of the designated breakglass accounts (breakglass1@contoso.onmicrosoft.com
or breakglass2@contoso.onmicrosoft.com
). If a member is not a breakglass account, the script prints a message indicating that this user “would be removed from PRA.”
Note: Replace the breakglass accounts with the corresponding accounts from your tenant.
Connect-MgGraph -Scopes RoleManagement.ReadWrite.Directory, Directory.Read.All $role = Get-MgDirectoryRole | Where-Object DisplayName -eq "Privileged Role Administrator" Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id | ForEach-Object { $u = Get-MgUser -UserId $_.Id -ErrorAction SilentlyContinue if ($u.UserPrincipalName -notin @("breakglass1@contoso.onmicrosoft.com","breakglass2@contoso.onmicrosoft.com")) { "{0} would be removed from PRA" -f $u.UserPrincipalName } }
Result:
This confirms that the test account is not part of break-glass accounts and must be removed safely.
Microsoft 365 Hardening with PIM and Conditional Access
To prevent future escalation, we implemented identity governance best practices:
- Minimize PRA assignments – Reserve for emergency break-glass accounts
- Enable Privileged Identity Management (PIM) – MFA, approval workflows, justification, and time-limited activation
- Scope access using Administrative Units (AUs) – Restrict administrative privileges by department or region
- Apply Conditional Access policies – Protect all admin portals
- Continuous monitoring and alerting – Forward PIM logs to Azure Log Analytics
- With PIM, all admin role activations are auditable, temporary, and approval-based, reducing risk.