Forum Discussion
Amina_Aggarwal
Nov 07, 2022Copper Contributor
Privileged Accounts - Sign in Failure Spikes (Built-In Analytics Rule)
Hi ,
I am trying to test this rule but unable to understand the following fields and thresholds set in the rule (PartialFailedSignins, TotalFailedSignins, let scorethreshold = 3;
let baselinethreshold = 3; ) Can anyone help me understand these fields and the values assigned to these fields.
let starttime = 14d;
let timeframe = 1d;
let scorethreshold = 3;
let baselinethreshold = 3;
let aadFunc = (tableName:string){
IdentityInfo
| where TimeGenerated > ago(starttime)
| summarize arg_max(TimeGenerated, *) by AccountUPN
| mv-expand AssignedRoles
| where AssignedRoles matches regex 'Admin'
| summarize Roles = make_list(AssignedRoles) by AccountUPN = tolower(AccountUPN)
| join kind=inner (
table(tableName)
| where TimeGenerated between (startofday(ago(starttime))..startofday(now()))
| where ResultType != 0
| extend UserPrincipalName = tolower(UserPrincipalName)
) on $left.AccountUPN == $right.UserPrincipalName
| extend timestamp = TimeGenerated, AccountCustomEntity = UserPrincipalName, Roles = tostring(Roles)
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
let allSignins = union isfuzzy=true aadSignin, aadNonInt;
let TimeSeriesAlerts =
allSignins
| make-series HourlyCount=count() on TimeGenerated from startofday(ago(starttime)) to startofday(now()) step 1h by UserPrincipalName, Roles
| extend (anomalies, score, baseline) = series_decompose_anomalies(HourlyCount, scorethreshold, -1, 'linefit')
| mv-expand HourlyCount to typeof(double), TimeGenerated to typeof(datetime), anomalies to typeof(double), score to typeof(double), baseline to typeof(long)
// Filtering low count events per baselinethreshold
| where anomalies > 0 and baseline > baselinethreshold
| extend AnomalyHour = TimeGenerated
| project UserPrincipalName, Roles, AnomalyHour, TimeGenerated, HourlyCount, baseline, anomalies, score;
// Filter the alerts for specified timeframe
TimeSeriesAlerts
| where TimeGenerated > startofday(ago(timeframe))
| join kind=inner (
allSignins
| where TimeGenerated > startofday(ago(timeframe))
// create a new column and round to hour
| extend DateHour = bin(TimeGenerated, 1h)
| summarize PartialFailedSignins = count(), LatestAnomalyTime = arg_max(TimeGenerated, *) by bin(TimeGenerated, 1h), OperationName, Category, ResultType, ResultDescription, UserPrincipalName, Roles, UserDisplayName, AppDisplayName, ClientAppUsed, IPAddress, ResourceDisplayName
) on UserPrincipalName, $left.AnomalyHour == $right.DateHour
| project LatestAnomalyTime, OperationName, Category, UserPrincipalName, Roles = todynamic(Roles), UserDisplayName, ResultType, ResultDescription, AppDisplayName, ClientAppUsed, UserAgent, IPAddress, Location, AuthenticationRequirement, ConditionalAccessStatus, ResourceDisplayName, PartialFailedSignins, TotalFailedSignins = HourlyCount, baseline, anomalies, score
| extend timestamp = LatestAnomalyTime, IPCustomEntity = IPAddress, AccountCustomEntity = UserPrincipalName
No RepliesBe the first to reply