Query Details

Identity Potential MFA Number Matching Abuse

Query

//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']) > 2

Explanation

This 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.

Details

Matt Zorich profile picture

Matt Zorich

Released: June 29, 2022

Tables

SigninLogs

Keywords

SigninLogs,TimeGenerated,AuthenticationRequirement,AuthenticationDetails,UserPrincipalName,CorrelationId,ResultType,AuthResult

Operators

| project| where| mv-expand| extend| summarize| by| bin| array_length

Actions