Query Details
let User = "AccountName"; let PublicIp = (DeviceInfo | mv-expand todynamic(LoggedOnUsers) | extend ParsedLoggedOnUsers = parse_json(LoggedOnUsers) | extend LoggedOnUser = tostring(ParsedLoggedOnUsers.UserName) | where LoggedOnUser contains User | distinct PublicIP); AADSignInEventsBeta | where AccountUpn contains User and IPAddress !in (PublicIp) | project Timestamp, Application, ResourceDisplayName, LogonType, ErrorCode, SessionId, IPAddress, Country | join kind=inner (AADSignInEventsBeta | where IPAddress in (PublicIp)) on $left.SessionId == $right.SessionId | distinct Timestamp, SessionId, Application, ResourceDisplayName, Country, IPAddress, ErrorCode // Show only event with IPC alerts on SessionId //| join kind=innerunique (AlertEvidence | extend SessionId = tostring(todynamic(AdditionalFields).SessionId)) on $left.SessionId == $right.SessionId //| distinct Application, ResourceDisplayName, Country, IPAddress, ErrorCode, DetectionSource, Title // Show only event with IPC alerts on IPAddress //| join kind=innerunique (AlertEvidence | extend SessionId = tostring(todynamic(AdditionalFields).SessionId)) on $left.IPAddress == $right.RemoteIP //| distinct Application, ResourceDisplayName, Country, IPAddress, ErrorCode, DetectionSource, Title
The query is retrieving AAD sign-in events for a specific user. It first identifies the public IP addresses associated with the user's logged-on sessions. Then, it filters the sign-in events to exclude any events where the user's IP address matches the identified public IP addresses. The query then projects specific fields from the sign-in events and joins them with another set of sign-in events based on the session ID. Finally, it selects distinct fields from the joined events. The commented out sections suggest additional filtering options based on IPC alerts either on the session ID or IP address.

Thomas Naunheim
Released: August 23, 2023
Tables
Keywords
Operators