Query Details
id: c44269aa-9879-42d9-a8f4-56a93bb8c6ac
name: Granting of High-Risk Privilege Escalation Permissions to Service Principal
version: 1.0.4
kind: Scheduled
description: |
This rule identifies when a Service Principal is granted specific, high-risk Application Permissions for Microsoft Graph that can lead to immediate tenant-wide privilege escalation.
The query monitors AuditLogs for successful "Add app role assignment to service principal" operations. It specifically looks for the addition of the following sensitive permission GUIDs:
* RoleManagement.ReadWrite.Directory (9e3f62cf...): Allows the app to grant itself or others any role, including Global Administrator.
* AppRoleAssignment.ReadWrite.All (06b708a9...): Allows the app to grant additional permissions to applications, enabling a path to grant the permission above.
* Application.ReadWrite.All (1bfefb4e...): Allows the app to modify other applications, potentially adding credentials to run as a highly privileged identity.
If an attacker compromises an account with the ability to grant admin consent (or compromises an existing Service Principal with AppRoleAssignment.ReadWrite.All), they can assign these permissions to a backdoor Service Principal to achieve persistence and full dominance over the Entra ID tenant.
severity: High
queryFrequency: 31m
queryPeriod: 31m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Persistence
query: |-
let DangerousAPIPermissions = dynamic({
"9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8": "RoleManagement.ReadWrite.Directory -> Directly promote any user to global admin",
"06b708a9-e830-4db3-a914-8e69da51d44f": "AppRoleAssignment.ReadWrite.All -> Grant RoleManagement.ReadWrite.Directory, then promote to global admin",
"1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9": "Application.ReadWrite.All -> Act as another entity e.g. a global admin user"
});
AuditLogs
| where OperationName == "Add app role assignment to service principal"
| where Result =~ "success"
| mv-expand TargetResources
| where TargetResources.displayName == "Microsoft Graph"
| mv-expand TargetResources.modifiedProperties
| where TargetResources_modifiedProperties.displayName == "AppRole.Id"
// This permission was not part of this application before
| where isnull(TargetResources_modifiedProperties.oldValue)
// The new permission is part of the dangerous API permissions
| extend NewAPIPermission = trim('"', tostring(TargetResources_modifiedProperties.newValue))
| extend PotentialImpact = DangerousAPIPermissions[NewAPIPermission]
| where isnotempty(PotentialImpact)
| extend UserAgent = iff(AdditionalDetails[0].key == "User-Agent", tostring(AdditionalDetails[0].value), "")
| extend ServicePrincipalDisplayName = parse_json(tostring(parse_json(tostring(TargetResources.modifiedProperties))[6].newValue))
| extend ServicePrincipalObjectID = parse_json(tostring(parse_json(tostring(TargetResources.modifiedProperties))[5].newValue))
| extend InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
| extend InitiatingIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress), tostring(InitiatedBy.user.ipAddress), tostring(InitiatedBy.app.ipAddress))
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: AllEntities
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []
eventGroupingSettings:
aggregationKind: SingleAlert
alertDetailsOverride:
alertDescriptionFormat: |-
A high impact Graph API permission was granted to an application.
The granted API permission was {{PotentialImpact}}
Please verify if this API permission is needed by this application and if so make sure to add it to the watchlist "HighRiskApps"
alertDynamicProperties: []
customDetails:
AddedPermission: NewAPIPermission
ServicePrincipal: ServicePrincipalDisplayName
ServicePrincipalId: ServicePrincipalObjectID
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InitiatingUserOrApp
- entityType: IP
fieldMappings:
- identifier: Address
columnName: InitiatingIpAddress
suppressionDuration: 5h
This query is designed to detect when a Service Principal in Microsoft Entra ID (formerly Azure AD) is granted high-risk permissions that could lead to privilege escalation across the tenant. Here's a simplified breakdown of what the query does:
Purpose: It identifies when specific, sensitive permissions are added to a Service Principal, which could allow an attacker to gain extensive control over the tenant if they compromise an account with admin consent capabilities.
Monitored Permissions: The query looks for the addition of three specific permissions:
Data Source: The query examines the AuditLogs for successful operations where an app role is assigned to a Service Principal.
Detection Logic:
Severity and Frequency: The rule is marked with high severity and runs every 31 minutes. An alert is triggered if any such permission assignment is detected.
Alerting: When a high-risk permission is granted, an alert is generated with details about the potential impact. It suggests verifying the necessity of the permission and considering adding the application to a watchlist if needed.
Incident Management: The rule creates incidents for each detection without grouping multiple events into a single alert.
Overall, this query helps security teams monitor and respond to potential privilege escalation risks by keeping track of sensitive permission assignments to Service Principals.

Fabian Bader
Released: February 5, 2026
Tables
Keywords
Operators