Query Details

Identity Potential Ai TM

Query

//Looks for potential AiTM phishing by finding sign ins with the following properties - has error codes 50074 (MFA required), 50140 (keep me signed in prompt) and 0 (success)
//It also looks for high or medium risk events and where there are multiple session id's per correlation id (per single sign in flow)

//Data connector required for this query - Azure Active Directory - Signin Logs

//Microsoft Sentinel doesn't track SessionId like Advanced Hunting does so you may end up with a few more false positives

SigninLogs
| where AppDisplayName == "OfficeHome"
| where UserPrincipalName has "@"
| summarize
    ErrorCodes=make_set(ResultType),
    RiskLevels=make_set_if(RiskLevelDuringSignIn, RiskLevelDuringSignIn != "none"),
    RiskTypes=make_set_if(RiskEventTypes, RiskEventTypes != "[]")
    by CorrelationId, UserPrincipalName
| where ErrorCodes has_all (0, 50140, 50074)
    and RiskLevels has_any ("medium", "high")
| extend ['Count of RiskTypes']=array_length(RiskTypes)
| where ['Count of RiskTypes'] > 0

//Advanced Hunting query, includes SessionId's 

//Data connector required for this query - Advanced Hunting with Azure AD P2 License

AADSignInEventsBeta
| where Application == "OfficeHome"
| where AccountUpn has "@"
| summarize
    ErrorCodes=make_set(ErrorCode),
    RiskLevels=make_set_if(RiskLevelDuringSignIn, isnotempty(RiskLevelDuringSignIn)),
    RiskTypes=make_set_if(RiskEventTypes, isnotempty(RiskEventTypes)),
    SessionIds=make_set_if(SessionId, isnotempty(SessionId))
    by CorrelationId, AccountUpn
| where ErrorCodes has_all (0, 50140, 50074)
    and RiskLevels has_any ("50", "100") 
| extend ['Count of SessionIds']=array_length(SessionIds)
| extend ['Count of RiskTypes']=array_length(RiskTypes)
| where ['Count of SessionIds'] >= 2 and ['Count of RiskTypes'] > 0

//If you want to make a detection rule for this in Advanced Hunting you will just need to first find the suspicious correlationIds, then go back and find them so M365 Defender can map the fields properly
//Advanced Hunting needs a timestamp to create a detection. You could alternatively add a first/last event time to the query, but I prefer this way

let ids=
AADSignInEventsBeta
| where Application == "OfficeHome"
| where AccountUpn has "@"
| summarize
    ErrorCodes=make_set(ErrorCode),
    RiskLevels=make_set_if(RiskLevelDuringSignIn, isnotempty(RiskLevelDuringSignIn)),
    RiskTypes=make_set_if(RiskEventTypes, isnotempty(RiskEventTypes)),
    SessionIds=make_set_if(SessionId, isnotempty(SessionId))
    by CorrelationId, AccountUpn
| where ErrorCodes has_all (0, 50140, 50074)
    and RiskLevels has_any ("50", "100")
| extend ['Count of SessionIds']=array_length(SessionIds)
| extend ['Count of RiskTypes']=array_length(RiskTypes)
| where ['Count of SessionIds'] >= 2 and ['Count of RiskTypes'] > 0
| distinct CorrelationId;
AADSignInEventsBeta
| where CorrelationId in (ids)
| summarize arg_min(Timestamp, *) by CorrelationId //grab the first event per correlationid to allow Advanced Hunting field mapping

Explanation

This query is looking for potential phishing attempts in Azure Active Directory sign-in logs. It searches for sign-ins with specific error codes (50074, 50140, and 0) and high or medium risk levels. It also checks for multiple session IDs per correlation ID. The query is split into two parts, one for regular sign-in logs and another for advanced hunting with additional fields like session IDs. The query can be used to create a detection rule in Advanced Hunting by finding suspicious correlation IDs and mapping the fields properly.

Details

Matt Zorich profile picture

Matt Zorich

Released: August 25, 2023

Tables

SigninLogsAADSignInEventsBeta

Keywords

SigninLogs,AppDisplayName,UserPrincipalName,ResultType,RiskLevelDuringSignIn,RiskEventTypes,CorrelationId,ErrorCodes,RiskLevels,RiskTypes,CountofRiskTypes AADSignInEventsBeta,Application,AccountUpn,ErrorCode,RiskLevelDuringSignIn,RiskEventTypes,SessionId,CorrelationId,ErrorCodes,RiskLevels,SessionIds,CountofSessionIds,CountofRiskTypes,Timestamp

Operators

wherehassummarizemake_setmake_set_ifbyhas_allhas_anyextendarray_lengthisnotemptyindistinctarg_min

Actions