Malicious OAuth App & Consent Risk Matrix
CRITICAL PERSISTENCE
GRAPH API & OAUTH 2.0
Adversaries increasingly favor OAuth Application Abuse over traditional password compromise. By tricking a user into granting permissions to a rogue cloud application, the adversary secures permanent API access to emails, files, and directory objects - completely bypassing MFA, password changes, and Conditional Access policies.
⚠️ High-Risk Microsoft Graph Permissions Matrix
Section titled “⚠️ High-Risk Microsoft Graph Permissions Matrix”| Permission Name | Type | Potential Impact | Abuse Scenario |
|---|---|---|---|
Mail.ReadWrite | Delegated / App | Full access to user or all tenant mailboxes | Mass email exfiltration, wire fraud, message tampering |
Mail.Send | Delegated / App | Send emails as the victim or arbitrary user | Internal spear-phishing, spreading malicious links |
Files.ReadWrite.All | Delegated / App | Read and write access to all SharePoint and OneDrive files | Data extortion, mass file download, ransomware encryption |
Directory.ReadWrite.All | App | Modify any directory object | Creating backdoor admin users, changing group memberships |
RoleManagement.ReadWrite.Directory | App | Grant arbitrary directory roles | Elevating any compromised identity to Global Administrator |
User.ReadWrite.All | Delegated / App | Modify all user profiles | Resetting user authentication methods or adding secondary phones |
offline_access | Delegated | Long-lived refresh token acquisition | Accessing APIs persistently without user interaction |
🔎 KQL Threat Hunting: OAuth Abuse Telemetry
Section titled “🔎 KQL Threat Hunting: OAuth Abuse Telemetry”Monitor Microsoft Entra ID audit logs (AuditLogs table in Sentinel / Defender XDR) for app registration and consent anomalies:
1. Detect Newly Added Credentials to Service Principals
Section titled “1. Detect Newly Added Credentials to Service Principals”Adversaries with Application Administrator privileges add certificates or client secrets to existing high-privilege apps:
AuditLogs| where TimeGenerated > ago(14d)| where OperationName in ("Add service principal credentials", "Update service principal")| extend TargetApp = tostring(TargetResources[0].displayName)| extend Initiator = tostring(InitiatedBy.user.userPrincipalName)| project TimeGenerated, OperationName, TargetApp, Initiator, Result, AdditionalDetails| order by TimeGenerated desc2. Detect High-Risk User Consent Grants
Section titled “2. Detect High-Risk User Consent Grants”AuditLogs| where TimeGenerated > ago(14d)| where OperationName == "Consent to application"| extend AppName = tostring(TargetResources[0].displayName)| extend ConsentingUser = tostring(InitiatedBy.user.userPrincipalName)| extend Permissions = tostring(TargetResources[0].modifiedProperties)| project TimeGenerated, AppName, ConsentingUser, Permissions, Result| order by TimeGenerated desc⚡ PowerShell: Audit & Revoke Illicit OAuth Grants
Section titled “⚡ PowerShell: Audit & Revoke Illicit OAuth Grants”Run these commands with Application.ReadWrite.All and DelegatedPermissionGrant.ReadWrite.All privileges:
Inventory All Delegated OAuth Grants
Section titled “Inventory All Delegated OAuth Grants”# Connect to Microsoft Graph# Connect-MgGraph -Scopes "DelegatedPermissionGrant.ReadWrite.All", "Application.ReadWrite.All"
$grants = Get-MgOauth2PermissionGrant$report = foreach ($g in $grants) { $sp = Get-MgServicePrincipal -ServicePrincipalId $g.ClientId [PSCustomObject]@{ GrantId = $g.Id AppName = $sp.DisplayName ClientId = $g.ClientId ConsentType = $g.ConsentType Scope = $g.Scope PrincipalId = $g.PrincipalId }}$report | Format-Table -AutoSizeEmergency Revocation of an Illicit Grant
Section titled “Emergency Revocation of an Illicit Grant”# 1. Revoke the delegated permission grant$targetGrantId = "ROGuE_GRANT_ID_HERE"Remove-MgOauth2PermissionGrant -OAuth2PermissionGrantId $targetGrantIdWrite-Host "[+] OAuth permission grant revoked." -ForegroundColor Green
# 2. Disable the malicious Service Principal completely$targetClientId = "ROGUE_CLIENT_ID_HERE"Update-MgServicePrincipal -ServicePrincipalId $targetClientId -AccountEnabled $falseWrite-Host "[+] Service Principal disabled." -ForegroundColor Yellow