Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Anomalous sign-in location by user account and authenticating application

Back
Id7cb8f77d-c52f-4e46-b82f-3cf2e106224a
RulenameAnomalous sign-in location by user account and authenticating application
DescriptionThis query over Microsoft Entra ID sign-in considers all user sign-ins for each Microsoft Entra ID application and picks out the most anomalous change in location profile for a user within an individual application.
SeverityMedium
TacticsInitialAccess
TechniquesT1078
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1d
Query period7d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml
Version2.0.5
Arm template7cb8f77d-c52f-4e46-b82f-3cf2e106224a.json
Deploy To Azure
// Adjust this figure to adjust how sensitive this detection is
let sensitivity = 2.5;
// Adjust this figure to set the value that defines the requested estimation accuracy. The default value is 1. Possible values are 0, 1, 2, 3, 4.
let dcountAccuracy = 1;
let AuthEvents = materialize(
union isfuzzy=True SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated between (ago(7d) .. now())
| where ResultType == 0
| extend LocationDetails = LocationDetails_dynamic
| extend Location = strcat(LocationDetails.countryOrRegion, "-", LocationDetails.state,"-", LocationDetails.city)
| where Location != "--");
AuthEvents
| summarize dcount(Location, dcountAccuracy) by AppDisplayName, AppId, UserPrincipalName, UserId, bin(startofday(TimeGenerated), 1d)
| where dcount_Location > 2
| make-series CountOfLocations = sum(dcount_Location) on TimeGenerated  step 1d by AppId, UserId
| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(CountOfLocations, sensitivity, -1, 'linefit')
| mv-expand CountOfLocations to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
| where Anomalies > 0 and Baseline > 0
| join kind=inner( AuthEvents | extend TimeStamp = startofday(TimeGenerated)) on UserId, AppId
| extend SignInDetails = bag_pack("TimeGenerated", TimeGenerated1, "Location", Location, "Source", IPAddress, "Device", DeviceDetail_dynamic)
| summarize SignInDetailsSet=make_set(SignInDetails, 1000) by UserId, UserPrincipalName, CountOfLocations, TimeGenerated, AppId, AppDisplayName
| extend Name = split(UserPrincipalName, "@")[0], UPNSuffix = split(UserPrincipalName, "@")[1]
description: |
    'This query over Microsoft Entra ID sign-in considers all user sign-ins for each Microsoft Entra ID application and picks out the most anomalous change in location profile for a user within an individual application.
version: 2.0.5
triggerThreshold: 0
tactics:
- InitialAccess
queryPeriod: 7d
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml
triggerOperator: gt
status: Available
alertDetailsOverride:
  alertDisplayNameFormat: Anomalous sign-in location by {{UserPrincipalName}} to {{AppDisplayName}}
  alertDescriptionFormat: |
    This query over Microsoft Entra ID sign-in considers all user sign-ins for each Microsoft Entra ID application and picks out the most anomalous change in location profile for a user within an
    individual application. This has detected {{UserPrincipalName}} signing into {{AppDisplayName}} from {{CountOfLocations}} 
    different locations.
eventGroupingSettings:
  aggregationKind: SingleAlert
id: 7cb8f77d-c52f-4e46-b82f-3cf2e106224a
name: Anomalous sign-in location by user account and authenticating application
queryFrequency: 1d
severity: Medium
customDetails:
  Application: AppDisplayName
kind: Scheduled
entityMappings:
- fieldMappings:
  - columnName: UserPrincipalName
    identifier: FullName
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: UserId
    identifier: AadUserId
  entityType: Account
relevantTechniques:
- T1078
query: |
  // Adjust this figure to adjust how sensitive this detection is
  let sensitivity = 2.5;
  // Adjust this figure to set the value that defines the requested estimation accuracy. The default value is 1. Possible values are 0, 1, 2, 3, 4.
  let dcountAccuracy = 1;
  let AuthEvents = materialize(
  union isfuzzy=True SigninLogs, AADNonInteractiveUserSignInLogs
  | where TimeGenerated between (ago(7d) .. now())
  | where ResultType == 0
  | extend LocationDetails = LocationDetails_dynamic
  | extend Location = strcat(LocationDetails.countryOrRegion, "-", LocationDetails.state,"-", LocationDetails.city)
  | where Location != "--");
  AuthEvents
  | summarize dcount(Location, dcountAccuracy) by AppDisplayName, AppId, UserPrincipalName, UserId, bin(startofday(TimeGenerated), 1d)
  | where dcount_Location > 2
  | make-series CountOfLocations = sum(dcount_Location) on TimeGenerated  step 1d by AppId, UserId
  | extend (Anomalies, Score, Baseline) = series_decompose_anomalies(CountOfLocations, sensitivity, -1, 'linefit')
  | mv-expand CountOfLocations to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
  | where Anomalies > 0 and Baseline > 0
  | join kind=inner( AuthEvents | extend TimeStamp = startofday(TimeGenerated)) on UserId, AppId
  | extend SignInDetails = bag_pack("TimeGenerated", TimeGenerated1, "Location", Location, "Source", IPAddress, "Device", DeviceDetail_dynamic)
  | summarize SignInDetailsSet=make_set(SignInDetails, 1000) by UserId, UserPrincipalName, CountOfLocations, TimeGenerated, AppId, AppDisplayName
  | extend Name = split(UserPrincipalName, "@")[0], UPNSuffix = split(UserPrincipalName, "@")[1]
requiredDataConnectors:
- dataTypes:
  - SigninLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - AADNonInteractiveUserSignInLogs
  connectorId: AzureActiveDirectory