Query Details

RULE 10 SP CA Bypass Management Ops

Query

// Rule    : Azure - Service Principal CA Bypass Sign-in Followed by Management Operations
// Severity: High
// Tactics : InitialAccess, CredentialAccess
// MITRE   : T1528, T1078
// Freq    : PT1H   Period: PT2H
//==========================================================================================

let CABypassSignins = AADServicePrincipalSignInLogs
    | where TimeGenerated > ago(2h)
    | where ResultType == 0
    | where ConditionalAccessStatus has_any ("failure", "notApplied")
    | where isnotempty(IPAddress)
    | where IPAddress !startswith "168.63." and IPAddress !startswith "169.254."
    | project SigninTime = TimeGenerated, ServicePrincipalId, ServicePrincipalName, SigninIP = IPAddress, AppId, ConditionalAccessStatus;
AzureActivity
| where TimeGenerated > ago(2h)
| where ActivityStatusValue =~ "Success"
| where OperationNameValue has_any ("WRITE", "DELETE", "ACTION")
| where not(OperationNameValue has_any ("READ", "LIST", "GET", "LISTKEYS"))
| where isnotempty(CallerIpAddress)
| join kind=inner CABypassSignins on $left.CallerIpAddress == $right.SigninIP
| where TimeGenerated > SigninTime and TimeGenerated <= SigninTime + 1h
| summarize
    MGMTOpCount = count(),
    Operations = make_set(OperationNameValue, 10),
    AffectedResources = make_set(ResourceId, 10),
    SubscriptionIds = make_set(SubscriptionId, 5),
    CallerIP = any(CallerIpAddress),
    CAStatus = any(ConditionalAccessStatus),
    FirstMGMTOp = min(TimeGenerated),
    LastMGMTOp = max(TimeGenerated)
    by Caller, ServicePrincipalName, SigninTime
// Tuned: raised burst threshold 2 -> 3 (single opportunistic mgmt call after CA-bypass sign-in
// was the dominant FP; 3+ ops within 1h is much more indicative of actual token abuse).
| where MGMTOpCount >= 3
| extend
    AccountName = coalesce(tostring(split(Caller, "@")[0]), ServicePrincipalName),
    AccountUPNSuffix = tostring(split(Caller, "@")[1])

Explanation

This query is designed to detect potentially suspicious activity involving Azure Service Principals. Here's a simplified explanation:

  1. Purpose: The query aims to identify instances where a Service Principal in Azure bypasses Conditional Access (CA) policies during sign-in and then performs multiple management operations within a short period. This could indicate unauthorized access or token abuse.

  2. Severity and Tactics: The activity is considered high severity and relates to tactics like Initial Access and Credential Access, as defined by the MITRE ATT&CK framework.

  3. Data Sources:

    • AADServicePrincipalSignInLogs: This part of the query looks for Service Principal sign-ins within the last 2 hours where the sign-in was successful (ResultType == 0), but Conditional Access policies either failed or were not applied. It filters out internal IP addresses and captures relevant details like the sign-in time, Service Principal ID, and IP address.
    • AzureActivity: This part examines Azure management operations (like WRITE, DELETE, ACTION) that were successful within the last 2 hours. It excludes read-only operations and joins this data with the sign-in logs based on matching IP addresses.
  4. Analysis:

    • The query checks if these management operations occurred within 1 hour after the suspicious sign-in.
    • It summarizes the data to count the number of management operations, list the types of operations, affected resources, and subscriptions involved.
    • It ensures that at least 3 management operations occurred within this timeframe to reduce false positives.
  5. Output:

    • The query provides details like the Service Principal name, the number of operations, the types of operations, and the time of the first and last management operation.
    • It also extracts and formats the account name and domain from the caller's email address.

Overall, this query helps identify potential security incidents where a Service Principal might be used to perform unauthorized actions in Azure after bypassing security controls.

Details

David Alonso profile picture

David Alonso

Released: July 27, 2026

Tables

AADServicePrincipalSignInLogsAzureActivity

Keywords

AzureActivityServicePrincipalSigninLogsIPAddressOperationNameResourceIdSubscriptionCallerConditionalAccessStatusAccountUPNSuffix

Operators

let|where>ago()==has_any()isnotempty()!startswithproject=~joinonsummarizecount()make_set()any()min()max()byextendcoalesce()tostring()split()>=

MITRE Techniques

Actions

GitHub