Query Details
// Rule : Workload Identity - Managed Identity Anomalous Activity Outside Business Hours
// Severity: Medium
// Tactics : Persistence, LateralMovement
// MITRE : T1078.004, T1550
// Freq : PT1H Period: PT1H
//==========================================================================================
// Business hours baseline: 06:00–22:00 weekdays
// Managed Identities authenticating heavily at night/weekends may indicate
// a compromised workload, repurposed VM/container, or attacker pivoting via MI
// --- isfuzzy=true + datatable fallback: deployment succeeds even if AADManagedIdentitySignInLogs is not yet enabled ---
// ---- Network Allowlist (exclude trusted IPs / CIDR / ranges) --------------
let _allow = materialize(union isfuzzy=true (print R="" | take 0), (_GetWatchlist('NetworkAllowlist') | project R = tostring(IPOrRange)) | where isnotempty(R));
let _allowCIDR = toscalar(_allow | where not(R matches regex @'^\d+\.\d+\.\d+\.\d+-\d+\.\d+\.\d+\.\d+$') | extend R = iff(R has '/', R, strcat(R, '/32')) | summarize make_list(R));
let _allowRange = toscalar(_allow | where R matches regex @'^\d+\.\d+\.\d+\.\d+-\d+\.\d+\.\d+\.\d+$' | summarize make_list(R));
let _ExcludeAllowlistedIPs = (T:(IPAddress:string)) {
T
| extend IPAddress = tostring(IPAddress)
| where array_length(_allowCIDR) == 0 or isnull(ipv4_is_in_any_range(IPAddress, _allowCIDR)) or not(ipv4_is_in_any_range(IPAddress, _allowCIDR))
| mv-apply _r = _allowRange to typeof(string) on (
extend _lo = tostring(split(_r,'-')[0]), _hi = tostring(split(_r,'-')[1])
| extend _inRange = ipv4_compare(IPAddress, _lo) >= 0 and ipv4_compare(IPAddress, _hi) <= 0
| summarize _anyInRange = max(toint(_inRange)))
| where isnull(_anyInRange) or _anyInRange == 0
| project-away _anyInRange
};
// ---------------------------------------------------------------------------
let MILogs = union isfuzzy=true
(AADManagedIdentitySignInLogs | invoke _ExcludeAllowlistedIPs()),
(datatable(TimeGenerated:datetime, ServicePrincipalId:string, ServicePrincipalName:string,
ResourceDisplayName:string, SourceAppClientId:string, ResultType:string)[]);
// --- Baseline: normal auth volume per MI during business hours (14d) ---
let BizHoursBaseline = MILogs
| where TimeGenerated between (ago(14d) .. ago(1h))
| where ResultType == "0"
| extend Hour = hourofday(TimeGenerated)
| extend IsWeekend = dayofweek(TimeGenerated) in (0d, 6d)
| where Hour >= 6 and Hour <= 22 and IsWeekend == false
| summarize
AvgHourlyAuth = avg(1.0), // will be computed per-day below
TotalBizAuth = count()
by ServicePrincipalId;
// --- Current hour ---
MILogs
| where TimeGenerated > ago(1h)
| where ResultType == "0"
| extend Hour = hourofday(TimeGenerated)
| extend IsWeekend = dayofweek(TimeGenerated) in (0d, 6d)
| extend IsOutOfHours = Hour < 6 or Hour > 22 or IsWeekend
| where IsOutOfHours
| summarize
AuthCount = count(),
UniqueResources = dcount(ResourceDisplayName),
Resources = make_set(ResourceDisplayName, 10),
SourceApps = make_set(SourceAppClientId, 10),
UniqueSourceApps = dcount(SourceAppClientId),
FirstActivity = min(TimeGenerated),
LastActivity = max(TimeGenerated)
by ServicePrincipalName, ServicePrincipalId
| where AuthCount > 50 or UniqueResources > 10
| join kind=leftouter BizHoursBaseline on ServicePrincipalId
| extend
IsHighVolume = AuthCount > 100,
IsHighSpread = UniqueResources > 10
This query is designed to detect unusual activity involving Managed Identities (MIs) outside of normal business hours, which could indicate potential security threats such as compromised workloads or unauthorized access. Here's a simplified breakdown of what the query does:
Define Business Hours: The query considers business hours to be from 6:00 AM to 10:00 PM on weekdays.
Network Allowlist: It sets up a list of trusted IP addresses or ranges to exclude them from analysis, ensuring that only untrusted or unknown IPs are considered for potential anomalies.
Log Collection: It gathers logs of Managed Identity sign-ins, excluding those from the allowlisted IPs.
Baseline Establishment: It calculates a baseline of normal authentication activity for each Managed Identity during business hours over the past 14 days. This includes average hourly authentications and total authentications during business hours.
Current Hour Analysis: The query then examines sign-in logs from the past hour, focusing on activity outside of business hours (either late at night, early morning, or weekends).
Anomaly Detection: It identifies Managed Identities with more than 50 authentications or access to more than 10 unique resources outside business hours. It checks if these numbers are significantly higher than the established baseline.
Output: The query outputs details of these potentially anomalous activities, including the count of authentications, unique resources accessed, source applications, and the time range of the activities.
Overall, this query helps in identifying suspicious activities that could indicate security threats, such as persistence or lateral movement tactics, by monitoring Managed Identity usage patterns outside of normal business hours.

David Alonso
Released: April 21, 2026
Tables
Keywords
Operators