// Illustrative; not run against live data. Microsoft Sentinel, Microsoft Entra ID sign-in logs (SigninLogs). // One address failing against many accounts, and any account that then signed in from it: // the shape of credential stuffing with leaked email and password pairs. let Start = datetime(2026-10-09T00:00:00Z); let FailureCodes = dynamic(["50126", "50053"]); // 50126: invalid username or password; 50053: account locked let TrustedEgress = dynamic(["REPLACE_WITH_CORPORATE_EGRESS_IP"]); let Attempts = SigninLogs | where TimeGenerated >= Start | where ResultType in (FailureCodes) | where not(IPAddress in (TrustedEgress)) | summarize FailedAccounts = dcount(UserPrincipalName), Failures = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by IPAddress, Hour = bin(TimeGenerated, 1h) | where FailedAccounts >= 10; Attempts | join kind=leftouter ( SigninLogs | where TimeGenerated >= Start | where ResultType == "0" | summarize SignedIn = make_set(UserPrincipalName, 50) by IPAddress ) on IPAddress | project Hour, IPAddress, FailedAccounts, Failures, FirstSeen, LastSeen, SignedIn | order by FailedAccounts desc