Microsoft Entra ID sign-in burst from multiple locations
Description
'Highlights accounts associated with multiple authentications from different geographical locations in a short period of time.'
Query · kql
let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let common_locations = (SigninLogs
| where TimeGenerated between(starttime..endtime)
| extend locationString= strcat(tostring(LocationDetails["countryOrRegion"]), "/",
tostring(LocationDetails["state"]))
| where locationString != "//"
| summarize count() by locationString
| take 100
| project locationString);
let signIns = (SigninLogs
| where TimeGenerated between(starttime..endtime)
| extend locationString= strcat(tostring(LocationDetails["countryOrRegion"]), "/",
tostring(LocationDetails["state"]))
| where locationString != "//" and locationString !endswith "/"
| where locationString !in (common_locations));
// Adjust these to tune query
let lookupWindow = 10m;
let lookupBin = lookupWindow / 2.0; // lookup bin = equal to 1/2 of the lookup window
let threshold = 2;
let users = (signIns
| summarize dcount(locationString) by Identity
| where dcount_locationString > threshold
| project Identity);
signIns
| where Identity in (users)
| project-rename Start=TimeGenerated
| extend TimeKey = bin(Start, lookupBin)
| join kind = inner (
signIns
| project-rename End=TimeGenerated, EndLocationString=locationString
// TimeKey on the right side of the join - emulates this authentication appearing several times
| extend TimeKey = range(bin(End - lookupWindow, lookupBin),
bin(End, lookupBin), lookupBin)
| mvexpand TimeKey to typeof(datetime) // translate TimeKey arrange range to a column
) on Identity, TimeKey
| where End > Start
| project tostring(Start), tostring(End), locationString, EndLocationString, UserPrincipalName, timeSpan = End - Start, Identity, IPAddress, UserAgent
| where locationString != EndLocationString
| summarize ips=makeset(IPAddress), UAs=makeset(UserAgent) by timeSpan, Identity, locationString, EndLocationString, Start, End, UserPrincipalName
| extend timestamp = Start, AccountCustomEntity = UserPrincipalName
| order by Identity