An adversary may be attempting to establish persistence by adding authentication methods or registering devices around a high-risk sign-in event. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential account compromise and unauthorized access attempts.
KQL Query
let Lookback = 1d;
let TimeDeltaThreshold = 5min;
SigninLogs
| where TimeGenerated >= ago(Lookback)
//Only interested in successful sign ins
| where ResultType == 0
//Look for high risk level sign ins only
| where RiskLevelDuringSignIn == "high"
//Exclude activity from Entra Named Locations and from trusted/registered devices
| where NetworkLocationDetails == "[]" and DeviceDetail.deviceId == ""
| summarize FirstRiskySignIn = min(TimeGenerated), RiskEvents = make_set_if(RiskEventTypes_V2, RiskEventTypes_V2!= "[]"), RiskySignInAppDisplayNames = make_set(AppDisplayName) by UserPrincipalName, RiskySignInIP=IPAddress, RiskySignInLocation=Location, UserId, RiskLevelDuringSignIn
//Check for authentication methods being registered and bring in details
| join kind=leftouter (
AuditLogs
| where TimeGenerated >= ago(Lookback)
| where Category != "ProvisioningManagement"
| where OperationName == "User registered security info" and Result == "success"
| project AuthMethodAddedTime=TimeGenerated, ResultReason, InitiatedBy, TargetResources, OperationName, Result, UserId=tostring(InitiatedBy.user.id), AuthMethodIP=tostring(InitiatedBy.user.ipAddress)
) on UserId
//Check for device registrations and bring in details
| join kind=leftouter (
AuditLogs
| where TimeGenerated >= ago(Lookback)
| where Category != "ProvisioningManagement"
| where OperationName == "Register device" and Result == "success"
| extend UserId = tostring(InitiatedBy.user.id), DeviceRegistrationIP = tostring(InitiatedBy.user.ipAddress)
| where UserId != ""
| project DeviceRegisteredTime=TimeGenerated, UserId, DeviceRegistrationIP, AdditionalDetails, OperationName, Result
| mv-apply AdditionalDetails on (
summarize by AdditionalDetails=tostring(bag_pack(tostring(AdditionalDetails.key),AdditionalDetails.value))
| summarize make_bag(todynamic(AdditionalDetails))
)
| extend RegisteredDeviceId = bag_AdditionalDetails.["Device Id"], RegisteredDeviceOS = bag_AdditionalDetails.["Device OS"], RegisteredDeviceTrustType = bag_AdditionalDetails.["Device Trust Type"]
) on UserId
| extend AuthTimeDelta = abs(AuthMethodAddedTime - FirstRiskySignIn), DeviceTimeDelta = abs(DeviceRegisteredTime - FirstRiskySignIn)
| where AuthTimeDelta <= TimeDeltaThreshold or DeviceTimeDelta <= TimeDeltaThreshold
| project FirstRiskySignIn, UserPrincipalName, RiskySignInIP, RiskySignInLocation, RiskEvents, RiskySignInAppDisplayNames, AuthMethodAddedTime, AuthTimeDelta, ResultReason, AuthMethodIP, DeviceRegisteredTime, DeviceTimeDelta, RegisteredDeviceId, RegisteredDeviceOS, RegisteredDeviceTrustType, DeviceRegistrationIP, UserId
| order by FirstRiskySignIn asc
id: d61c3213-77ba-4998-8818-1da2f85dacdf
name: High Risk Sign In Around Authentication Method Added or Device Registration
description: |
This query shows authentication methods being added and devices registered around the time of a high risk sign in which could indicate an attempt to establish persistence on a compromised account. The threshold can be changed to a wider timeframe if needed.
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
- SigninLogs
tactics:
- Persistence
relevantTechniques:
- T1556
query: |
let Lookback = 1d;
let TimeDeltaThreshold = 5min;
SigninLogs
| where TimeGenerated >= ago(Lookback)
//Only interested in successful sign ins
| where ResultType == 0
//Look for high risk level sign ins only
| where RiskLevelDuringSignIn == "high"
//Exclude activity from Entra Named Locations and from trusted/registered devices
| where NetworkLocationDetails == "[]" and DeviceDetail.deviceId == ""
| summarize FirstRiskySignIn = min(TimeGenerated), RiskEvents = make_set_if(RiskEventTypes_V2, RiskEventTypes_V2!= "[]"), RiskySignInAppDisplayNames = make_set(AppDisplayName) by UserPrincipalName, RiskySignInIP=IPAddress, RiskySignInLocation=Location, UserId, RiskLevelDuringSignIn
//Check for authentication methods being registered and bring in details
| join kind=leftouter (
AuditLogs
| where TimeGenerated >= ago(Lookback)
| where Category != "ProvisioningManagement"
| where OperationName == "User registered security info" and Result == "success"
| project AuthMethodAddedTime=TimeGenerated, ResultReason, InitiatedBy, TargetResources, OperationName, Result, UserId=tostring(InitiatedBy.user.id), AuthMethodIP=tostring(InitiatedBy.user.ipAddress)
) on UserId
//Check for device registrations and bring in details
| join kind=leftouter (
AuditLogs
| where TimeGenerated >= ago(Lookback)
| where Category != "ProvisioningManagement"
| where OperationName == "Register device" and Result == "success"
| extend UserId = tostring(InitiatedBy.user.id), DeviceRegistrationIP = tostring(InitiatedBy.user.ipAddress)
| where UserId != ""
| project DeviceRegisteredTime=TimeGenerated, UserId, DeviceRegistrationIP, AdditionalDetails, OperationName, Result
| mv-apply AdditionalDetails on (
summarize by AdditionalDetails=tostring(bag_pack(tostring(AdditionalDetails.key),AdditionalDetails.value))
| summarize make_bag(todynamic(AdditionalDetails))
)
| extend RegisteredDeviceId = bag_AdditionalDetails.["Device Id"], RegisteredDeviceOS = bag_AdditionalDetails.["Device OS"], RegisteredDeviceTrustType = bag_AdditionalDetails.["Device Trust Type"]
) on UserId
| extend AuthTimeDelta = abs(AuthMethodAddedTime - FirstRiskySignIn), DeviceTimeDelta = abs(DeviceRegisteredTime - FirstRiskySignIn)
| where AuthTimeDelta <= TimeDeltaThreshold
| Sentinel Table | Notes |
|---|---|
AuditLogs | Ensure this data connector is enabled |
SigninLogs | Ensure this data connector is enabled |
Scenario: Scheduled Job Execution
Description: A legitimate scheduled job runs during off-hours and triggers authentication method changes or device registration as part of its routine.
Filter/Exclusion: Exclude events where the user agent or source IP matches known internal job scheduler tools (e.g., cron, Windows Task Scheduler, Airflow, Jenkins), or where the activity is associated with a known scheduled task.
Scenario: Admin Task for Multi-Factor Authentication (MFA) Setup
Description: An admin is configuring MFA for a user, which involves adding an authentication method and registering a device.
Filter/Exclusion: Exclude events where the user has admin privileges or where the activity is associated with known admin tools (e.g., Azure AD Admin Portal, Microsoft Intune, Okta Admin Console).
Scenario: Device Registration for Remote Access Tools
Description: A system administrator registers a new device (e.g., a laptop or mobile device) for remote access to the network, which triggers device registration alerts.
Filter/Exclusion: Exclude events where the device is registered via known enterprise tools (e.g., Microsoft Intune, Jamf, Mobile Device Management (MDM)), or where the user is a system admin.
Scenario: Authentication Method Change for Compliance Purposes
Description: An internal audit or compliance task requires changing an authentication method (e.g., from password to certificate-based authentication), which triggers the rule.
Filter/Exclusion: Exclude events where the user is part of a compliance team or where the activity is logged under a known compliance tool (e.g., SAP GRC, IBM Security Access Manager, Compliance Manager).
Scenario: Device Registration for a New Employee Onboarding
Description: A new employee is being onboarded and