Query Details
//Detect when a user has been potentially comrpomised but is stopped by MFA number matching or otherwise denied. Even if stopped by MFA the users credentials need to be rotated.
//Data connector required for this query - Azure Active Directory - Signin Logs
//This query finds any time a user denies an authentication, enters the wrong number or just doesn't respond three or more times in a single sign in event
SigninLogs
| project
TimeGenerated,
AuthenticationRequirement,
AuthenticationDetails,
UserPrincipalName,
CorrelationId,
ResultType
| where ResultType == 500121
| mv-expand todynamic(AuthenticationDetails)
| extend AuthResult = tostring(parse_json(AuthenticationDetails).authenticationStepResultDetail)
| where AuthResult in ("MFA denied; user did not select the correct number", "MFA denied; user declined the authentication","MFA denied; user did not respond to mobile app notification")
//Create a list of denied MFA challenges by sign in attempt (single CorrelationId)
| summarize ['Result Types']=make_list(AuthResult) by CorrelationId, UserPrincipalName
//Find results where there are at least 3 failures within the same sign in, i.e three denies, three did not respond events or three did not select the correct number
| where array_length( ['Result Types']) > 2
//This is the same query but grouped by username and 10 minute period, in case the attacker is starting a new authentication flow and generates a new CorrelationId
SigninLogs
| project
TimeGenerated,
AuthenticationRequirement,
AuthenticationDetails,
UserPrincipalName,
CorrelationId,
ResultType
| where ResultType == 500121
| mv-expand todynamic(AuthenticationDetails)
| extend AuthResult = tostring(parse_json(AuthenticationDetails).authenticationStepResultDetail)
| where AuthResult in ("MFA denied; user did not select the correct number", "MFA denied; user declined the authentication","MFA denied; user did not respond to mobile app notification")
//Create a list of denied MFA challenges by UserPrincipalName and 10 minute window (to account for multiple sign in attempts)
| summarize ['Result Types']=make_list(AuthResult) by UserPrincipalName, bin(TimeGenerated, 10m)
//Find results where there are at least 3 failures within the same sign in, i.e three denies, three did not respond events or three did not select the correct number
| where array_length( ['Result Types']) > 2This query is used to detect potential compromises of user accounts in Azure Active Directory. It looks for instances where a user denies authentication, enters the wrong number, or fails to respond multiple times in a single sign-in event. The query uses the SigninLogs data connector and filters for ResultType 500121, which indicates a denial or failure in the authentication process.
The first part of the query groups the results by CorrelationId and UserPrincipalName, creating a list of denied MFA challenges for each sign-in attempt. It then filters for cases where there are at least three failures within the same sign-in event.
The second part of the query groups the results by UserPrincipalName and a 10-minute time window. This is useful in case the attacker starts a new authentication flow and generates a new CorrelationId. It again creates a list of denied MFA challenges for each user and time window, and filters for cases where there are at least three failures within the same sign-in attempts.

Matt Zorich
Released: June 29, 2022
Tables
Keywords
Operators