Query Details

HQ 012 Risky Sign In MFA Registration

Query

// HQ-012 — Risky Sign-In Followed by MFA Registration
// Purpose  : Detect when a user experiences a risky sign-in and then registers or modifies
//            an MFA/security-info method within a short window (default 4 hours).
//            Attackers who obtain credentials may immediately add their own MFA device
//            to maintain persistent access after a risk-flagged sign-in.
// Tables   : SigninLogs, AuditLogs
// MITRE    : TA0003 Persistence — T1098.005 Account Manipulation: Device Registration
//            TA0005 Defense Evasion — T1556.006 Modify Authentication Process: MFA
// Author   : Custom
// ---------------------------------------------------------------------------

let LookbackDays       = 14d;
let MFAChangeWindow    = 4h;        // Max time AFTER risky sign-in for MFA change to count
let MFAActivities = dynamic([
    "User registered security info",
    "User updated security info",
    "User deleted security info",
    "User changed default security info",
    "Register security info",
    "Delete security info",
    "User registered for multi-factor authentication",
    "User started security info registration",
    "User completed security info registration",
    "Admin updated user authentication method",
    "Update user"    // Covers StrongAuthenticationPhoneAppDetail modifications
]);
// ── Step 1: Risky sign-ins ──────────────────────────────────────────────────
let RiskySignIns = SigninLogs
| where TimeGenerated > ago(LookbackDays)
| where RiskLevelDuringSignIn in ("high", "medium")
    or RiskState    == "atRisk"
    or IsRisky      == true
| project
    SigninTime           = TimeGenerated,
    UserPrincipalName    = tolower(UserPrincipalName),
    RiskLevel            = RiskLevelDuringSignIn,
    RiskState,
    RiskDetail,
    RiskEventTypes       = tostring(RiskEventTypes_V2),
    IPAddress,
    AppDisplayName,
    ConditionalAccessStatus,
    SigninCorrelationId  = CorrelationId;
// ── Step 2: MFA registration / modification events ─────────────────────────
let MFARegistrations = AuditLogs
| where TimeGenerated > ago(LookbackDays)
| where ActivityDisplayName in~ (MFAActivities)
    // Narrow "Update user" to only those touching authentication methods
    or (ActivityDisplayName == "Update user"
        and tostring(AdditionalDetails) has_any ("StrongAuthentication", "PhoneAppDetail", "AuthenticationPhone"))
| extend ActorUPN = tolower(tostring(InitiatedBy.user.userPrincipalName))
| where isnotempty(ActorUPN)
| project
    MFATime       = TimeGenerated,
    ActorUPN,
    MFAActivity   = ActivityDisplayName,
    MFAResult     = Result,
    LoggedByService;
// ── Step 3: Correlate — MFA change occurring within window AFTER risky signin
RiskySignIns
| join kind=inner (MFARegistrations)
    on $left.UserPrincipalName == $right.ActorUPN
| where MFATime  >  SigninTime
    and MFATime  <= (SigninTime + MFAChangeWindow)
| extend TimeToMFAChange = MFATime - SigninTime
| project
    SigninTime,
    UserPrincipalName,
    RiskLevel,
    RiskState,
    RiskDetail,
    RiskEventTypes,
    IPAddress,
    AppDisplayName,
    ConditionalAccessStatus,
    MFATime,
    MFAActivity,
    MFAResult,
    TimeToMFAChange,
    SigninCorrelationId
| sort by SigninTime desc

Explanation

This query is designed to identify potentially malicious activity where a user experiences a risky sign-in and then registers or modifies their multi-factor authentication (MFA) settings shortly afterward. Here's a simplified breakdown of what the query does:

  1. Lookback Period: The query examines data from the past 14 days.

  2. Risky Sign-Ins: It first identifies sign-in attempts that are considered risky. This includes sign-ins with a high or medium risk level, those marked as "at risk," or explicitly flagged as risky. Relevant details such as the time of sign-in, user information, risk level, and IP address are extracted.

  3. MFA Activities: The query then looks for events where a user registers or modifies their MFA settings. This includes activities like registering security info, updating or deleting security info, and changes to authentication methods. It captures the time of these activities, the user involved, and the result of the activity.

  4. Correlation: The query correlates the risky sign-ins with subsequent MFA activities by the same user. It specifically looks for MFA changes that occur within 4 hours after a risky sign-in.

  5. Output: The final output lists details of the risky sign-ins and the corresponding MFA changes, including the time taken for the MFA change after the sign-in. This helps in identifying cases where an attacker might have gained access to an account and immediately set up their own MFA to maintain access.

Overall, this query is a security measure to detect and investigate suspicious account activities that could indicate a security breach.

Details

David Alonso profile picture

David Alonso

Released: April 6, 2026

Tables

SigninLogsAuditLogs

Keywords

RiskySigninMFASecurityInfoUserAuthenticationDeviceRegistrationAccountManipulationDefenseEvasion

Operators

letdynamicagoin==truetolowerprojecttostringwhereextendisnotemptyjoinon><=-sort bydeschas_anyin~

Actions