2024-03-15 // Dylan Evans
Unusual User Activity from New Geographic Locations
Microsoft SentinelDetects anomalous sign-in activity originating from geographic locations not previously observed for a user within a 14-day baseline period.
Unusual User Activity from New Geographic Locations
Overview
This detection identifies suspicious sign-in activity when a user logs in from a new geographic location outside their previously observed trusted regions. It combines Azure AD Behavior Analytics with SigninLogs to establish a baseline of legitimate user locations and flags deviations exceeding configurable thresholds for "unusual" behavior indicators.
Query
let baselineUnusualEvents = 10; //adjust this, lower = more sensitive/more results
let lookbackTime = ago(14d); //lookback time, generally the longer this is, the more records are checked against legit sources so results in less hits.
let RecentUserLocations = BehaviorAnalytics
| where TimeGenerated >= lookbackTime
| extend Country = case(
SourceIPLocation matches regex @".*,\s*(.+)$", extract(@".*,\s*(.+)$", 1, SourceIPLocation),
SourceIPLocation matches regex @"^[^,]+$", SourceIPLocation,
"Unknown"
)
| summarize RecentCountries = make_set(Country) by UserPrincipalName;
let LegitimateSignIns = SigninLogs // identify legitimate IPs based on user sign in activity
| where TimeGenerated >= lookbackTime
| where (isnotempty(DeviceDetail.deviceId) or isnotempty(MfaDetail.authMethod) or DeviceDetail.trustType has_any ("Azure AD Joined"))) // Trusted devices and IPs, you can add "Azure AD Registered" here as well if required
| where ResultType == 0
| summarize by UserPrincipalName, IPAddress;
BehaviorAnalytics
| extend ParsedInsights = parse_json(ActivityInsights)
| mv-expand bagexpansion=array Property = bag_keys(ParsedInsights) to typeof(string)
| extend Value = tostring(ParsedInsights[Property])
| where Value == "True"
| summarize TrueFieldsList = strcat_array(make_list(Property), ", "), TrueFieldCount = count(),
FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), OccurrenceCount = dcount(TimeGenerated)
by UserPrincipalName, IPAddress = SourceIPAddress, Location = SourceIPLocation
| where TrueFieldCount >= baselineUnusualEvents
| extend Country = case(
Location matches regex @".*,\s*(.+)$", extract(@".*,\s*(.+)$", 1, Location),
Location matches regex @"^[^,]+$", Location,
"Unknown"
)
| where not(Country has_any ("country1", "country2")) // Adjust trusted countries here
| join kind=leftouter RecentUserLocations on UserPrincipalName
| extend CountrySeen7Days = iff(set_has_element(RecentCountries, Country), "Yes", "No")
| where CountrySeen7Days == "No"
| join kind=leftanti LegitimateSignIns on UserPrincipalName, IPAddress
| project FirstSeen, LastSeen, UserPrincipalName, IPAddress, unusualActivityCount = TrueFieldCount, unusualActivityList = TrueFieldsList, Country, CountrySeen7Days
Logic Explanation
The query first establishes a baseline of user locations by analyzing BehaviorAnalytics records from the last 14 days. It then identifies suspicious events where:
- At least
baselineUnusualEvents(default: 10) boolean flags are triggered in ActivityInsights. - The event originates from an IP location not previously observed for that user within the lookback period.
- The location is excluded from a predefined list of trusted countries (
country1,country2).
It excludes:
- Trusted devices (Azure AD Joined, Azure AD Registered) with successful sign-ins (
ResultType == 0). - Records where the user has previously signed in from the same IP.
The detection flags events where the location is new to the user and not part of their historical activity.
Tuning Notes
- False positives from trusted countries: Lowering
baselineUnusualEventsincreases sensitivity but may flag legitimate travel.- Suggestion: Add more trusted country names or refine regex for country extraction.
- Lookback period too short: Shorter periods reduce false positives but may miss broader anomalies.
- Suggestion: Extend
lookbackTime(e.g., to 30 days) if the environment has stable user locations.
- Suggestion: Extend
- Boolean flags threshold: Adjust
baselineUnusualEventsbased on false positive rates in your environment.
References
- Microsoft Entra ID Behavior Analytics documentation: Azure AD Sign-in Reports
- IP geolocation parsing regex patterns for Azure AD logs.