Detection rules › Kusto
Suspicious Sign In Followed by MFA Modification
This query looks uses Microsoft Sentinel's UEBA features to look for suspicious logons followed by modifications to MFA settings by that user.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | T1078.004 Valid Accounts: Cloud Accounts |
| Persistence | T1556.006 Modify Authentication Process: Multi-Factor Authentication |
| Stealth | T1078.004 Valid Accounts: Cloud Accounts |
| Defense Impairment | T1556.006 Modify Authentication Process: Multi-Factor Authentication |
| Credential Access | T1556.006 Modify Authentication Process: Multi-Factor Authentication |
Event coverage
Rules detecting the same action
Other rules on this platform that filter on the same API call or operation.
- Authentication Method Changed for Privileged Account (Kusto)
- Authentication Methods Changed for Privileged Account (Kusto)
- Change to Authentication Method (Sigma)
- Guest Users Invited To Tenant By Non Approved Inviters (Sigma)
- Multi Factor Authentication Disabled For User Account (Sigma)
- New External User Granted Admin Role (Kusto)
- NRT Authentication Methods Changed for VIP Users (Kusto)
- Password Reset By User Account (Sigma)
Rule body kusto
id: aec77100-25c5-4254-a20a-8027ed92c46c
name: Suspicious Sign In Followed by MFA Modification
description: |
'This query looks uses Microsoft Sentinel's UEBA features to look for suspicious logons followed by modifications to MFA settings by that user.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
- connectorId: BehaviorAnalytics
dataTypes:
- BehaviorAnalytics
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
aggregationKind: AlertPerResult
status: Available
tactics:
- InitialAccess
- DefenseEvasion
relevantTechniques:
- T1078.004
- T1556.006
query: |
let PriorityScore = 9;
BehaviorAnalytics
| where ActionType == "Sign-in"
| where InvestigationPriority > PriorityScore
| extend UserPrincipalName = tolower(UserPrincipalName)
| extend LogOnTime = TimeGenerated
| join kind=inner (AuditLogs
| where Category =~ "UserManagement"
| where OperationName in~ ("Admin registered security info", "Admin updated security info", "Admin deleted security info", "User registered security info", "User changed default security info", "User deleted security info","User registered all required security info","User started security info registration")
| extend InitiatorUPN = tolower(tostring(InitiatedBy.user.userPrincipalName))
| extend InitiatorID = tostring(InitiatedBy.user.id)
| extend FromIP = tostring(InitiatedBy.user.ipAddress)
| extend TargetUPN = tolower(tostring(TargetResources[0].userPrincipalName))
| extend TargetId = tostring(TargetResources[0].id)
| extend MFAModTime = TimeGenerated
| where isnotempty(InitiatorUPN)) on $left.UserPrincipalName == $right.InitiatorUPN
| where MFAModTime between((LogOnTime-30m)..(LogOnTime+1h))
| extend InitiatorName = tostring(split(InitiatorUPN, "@")[0]), InitiatorUPNSuffix = tostring(split(InitiatorUPN, "@")[1]), TargetName = tostring(split(TargetUPN, "@")[0]), TargetUPNSuffix = tostring(split(TargetUPN, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InitiatorUPN
- identifier: Name
columnName: InitiatorName
- identifier: UPNSuffix
columnName: InitiatorUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: InitiatorID
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetUPN
- identifier: Name
columnName: TargetName
- identifier: UPNSuffix
columnName: TargetUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: TargetId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: FromIP
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIPAddress
alertDetailsOverride:
alertDisplayNameFormat: Suspicious Sign In by {{InitiatorUPN}} Followed by MFA Modification to {{TargetUPN}}
alertDescriptionFormat: |
This query looks uses Microsoft Sentinel's UEBA features to look for suspicious logons followed by modifications to MFA settings by that user.
In this case {{InitiatorUPN}} logged in followed by a modification to MFA settings for {{TargetUPN}}.
The sign in was from {{SourceIPAddress}}.
version: 1.0.1
kind: Scheduled
Stages and Predicates
Parameters
let PriorityScore = 9;
Stage 1: source
BehaviorAnalytics
Stage 2: where
| where ActionType == "Sign-in"
Stage 3: where
| where InvestigationPriority > PriorityScore
Stage 4: extend
| extend UserPrincipalName = tolower(UserPrincipalName)
Stage 5: extend
| extend LogOnTime = TimeGenerated
Stage 6: join
| join kind=inner (AuditLogs
| where Category =~ "UserManagement"
| where OperationName in~ ("Admin registered security info", "Admin updated security info", "Admin deleted security info", "User registered security info", "User changed default security info", "User deleted security info","User registered all required security info","User started security info registration")
| extend InitiatorUPN = tolower(tostring(InitiatedBy.user.userPrincipalName))
| extend InitiatorID = tostring(InitiatedBy.user.id)
| extend FromIP = tostring(InitiatedBy.user.ipAddress)
| extend TargetUPN = tolower(tostring(TargetResources[0].userPrincipalName))
| extend TargetId = tostring(TargetResources[0].id)
| extend MFAModTime = TimeGenerated
| where isnotempty(InitiatorUPN)) on $left.UserPrincipalName == $right.InitiatorUPN
Stage 7: where
| where MFAModTime between((LogOnTime-30m)..(LogOnTime+1h))
Stage 8: extend
| extend InitiatorName = tostring(split(InitiatorUPN, "@")[0]), InitiatorUPNSuffix = tostring(split(InitiatorUPN, "@")[1]), TargetName = tostring(split(TargetUPN, "@")[0]), TargetUPNSuffix = tostring(split(TargetUPN, "@")[1])
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
ActionType | eq |
|
Category | eq |
|
InitiatorUPN | is_not_null | |
InvestigationPriority | gt |
|
OperationName | in |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
UserPrincipalName | extend |
LogOnTime | extend |
InitiatorName | extend |
InitiatorUPNSuffix | extend |
TargetName | extend |
TargetUPNSuffix | extend |