High-privilege application role assigned to service principal
Description
Identifies application role assignments to service principals granting high-risk permissions such as Mail.ReadWrite, Directory.ReadWrite.All, or RoleManagement.ReadWrite.Directory, which provide tenant-wide API access without user context.
Query · kql
let timeframe = 1d;
let HighRiskRoles = dynamic([
"Mail.ReadWrite",
"Mail.Send",
"Files.ReadWrite.All",
"Directory.ReadWrite.All",
"RoleManagement.ReadWrite.Directory",
"Application.ReadWrite.All",
"AppRoleAssignment.ReadWrite.All",
"User.ReadWrite.All",
"full_access_as_app"
]);
AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName =~ "Add app role assignment to service principal"
| where Result =~ "success"
| extend ActorUpn = tostring(InitiatedBy.user.userPrincipalName)
| extend ActorApp = tostring(InitiatedBy.app.displayName)
| extend Actor = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
| extend ActorIp = iff(
isnotempty(tostring(InitiatedBy.user.ipAddress)),
tostring(InitiatedBy.user.ipAddress),
tostring(InitiatedBy.app.ipAddress))
| extend TargetSpName = tostring(TargetResources[0].displayName)
| extend TargetSpId = tostring(TargetResources[0].id)
| mv-expand ModProp = TargetResources[0].modifiedProperties
| where tostring(ModProp.displayName) =~ "AppRole.Value"
| extend AppRoleName = trim('"', tostring(ModProp.newValue))
| where AppRoleName in~ (HighRiskRoles)
| extend AccountName = iff(Actor has "@", tostring(split(Actor, "@")[0]), Actor)
| extend AccountUPNSuffix = iff(Actor has "@", tostring(split(Actor, "@")[1]), "")
| project TimeGenerated, Actor, AccountName, AccountUPNSuffix, ActorIp,
TargetSpName, TargetSpId, AppRoleName, CorrelationId
| sort by TimeGenerated desc