Query Details

Granting Of High Risk Privilege Escalation Permissions To Service Principal

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))

Explanation

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:

  1. 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.

  2. Monitored Permissions: The query looks for the addition of three specific permissions:

    • RoleManagement.ReadWrite.Directory: Allows the app to assign any role, including Global Administrator.
    • AppRoleAssignment.ReadWrite.All: Enables the app to grant additional permissions, potentially leading to the above permission.
    • Application.ReadWrite.All: Allows the app to modify other applications, possibly adding credentials to act as a highly privileged identity.
  3. Data Source: The query examines the AuditLogs for successful operations where an app role is assigned to a Service Principal.

  4. Detection Logic:

    • It checks if the operation was successful and if the permission was not previously assigned.
    • It identifies if the new permission is one of the high-risk permissions listed.
    • It captures details such as the user or app that initiated the change, the IP address, and the Service Principal involved.
  5. 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.

  6. 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.

  7. 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.