Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ name: MFA Rejected by User
description: |
'Identifies occurances where a user has rejected an MFA prompt. This could be an indicator that a threat actor has compromised the username and password of this user account and is using it to try and log into the account.
Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins
This query has also been updated to include UEBA logs IdentityInfo and BehaviorAnalytics for contextual information around the results.'
This query has also been updated to include UEBA logs IdentityInfo and BehaviorAnalytics for contextual information around the results.
Please note, MFA Failed logons from known IP ranges can be benign depending on the conditional access policies. In case of noisy behavior, consider tuning the source IP ranges or location filter after careful consideration'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
Expand All @@ -27,13 +28,13 @@ relevantTechniques:
tags:
- AADSecOpsGuide
query: |
let riskScoreCutoff = 20; //Adjust this based on volume of results
let riskScoreCutoff = 3; //Adjust this score threshold based on volume of results. Activities identified as the most abnormal receive the highest scores (on a scale of 0-10)
SigninLogs
| where ResultType == 500121
| extend additionalDetails_ = tostring(Status.additionalDetails)
| extend UserPrincipalName = tolower(UserPrincipalName)
| where additionalDetails_ =~ "MFA denied; user declined the authentication" or additionalDetails_ has "fraud"
| summarize StartTime = min(TimeGenerated), EndTIme = max(TimeGenerated) by UserPrincipalName, UserId, AADTenantId, IPAddress
| summarize StartTime = min(TimeGenerated), EndTIme = max(TimeGenerated) by UserPrincipalName, UserId, AADTenantId, FailedIPAddress = IPAddress
| extend Name = tostring(split(UserPrincipalName,'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName,'@',1)[0])
| join kind=leftouter (
IdentityInfo
Expand All @@ -48,19 +49,19 @@ query: |
by AccountUPN
| extend UserPrincipalName=tolower(AccountUPN)
) on UserPrincipalName
//Below it will be joined with BehaviorAnalytics table to the Failed IP Addresses
| join kind=leftouter (
BehaviorAnalytics
| where ActivityType in ("FailedLogOn", "LogOn")
| where isnotempty(SourceIPAddress)
| project UsersInsights, DevicesInsights, ActivityInsights, InvestigationPriority, SourceIPAddress
| project-rename IPAddress = SourceIPAddress
| project UsersInsights, DevicesInsights, ActivityInsights, InvestigationPriority, SourceIPAddress, UserName
| project-rename FailedIPAddress = SourceIPAddress, Name = UserName
| summarize
UsersInsights = make_set(UsersInsights, 1000),
DevicesInsights = make_set(DevicesInsights, 1000),
IPInvestigationPriority = sum(InvestigationPriority)
by IPAddress)
on IPAddress
| extend UEBARiskScore = IPInvestigationPriority
MaxInvestigationScore = max(InvestigationPriority) // Only retrieve maximum Investigation Property score for both FailedIP and User
by FailedIPAddress, Name)
on FailedIPAddress, Name // Joining on both IP and User so as to only return context associated with same user
| extend UEBARiskScore = MaxInvestigationScore
| project-away *1 // removing duplicate columns post outer join from output
| where UEBARiskScore > riskScoreCutoff
| sort by UEBARiskScore desc
entityMappings:
Expand All @@ -79,6 +80,6 @@ entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPAddress
version: 2.0.3
columnName: FailedIPAddress
version: 2.0.4
kind: Scheduled
2 changes: 1 addition & 1 deletion Solutions/Microsoft Entra ID/Data/Solution_AAD.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"Solutions/Microsoft Entra ID/Playbooks/Revoke-AADSignInSessions/entity-trigger/azuredeploy.json"
],
"BasePath": "C:\\GitHub\\Azure-Sentinel",
"Version": "3.2.9",
"Version": "3.2.10",
"Metadata": "SolutionMetadata.json",
"TemplateSpec": true,
"StaticDataConnectorIds": [
Expand Down
Binary file added Solutions/Microsoft Entra ID/Package/3.2.10.zip
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@
"name": "analytic32-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Identifies occurances where a user has rejected an MFA prompt. This could be an indicator that a threat actor has compromised the username and password of this user account and is using it to try and log into the account.\nRef : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins\nThis query has also been updated to include UEBA logs IdentityInfo and BehaviorAnalytics for contextual information around the results."
"text": "Identifies occurances where a user has rejected an MFA prompt. This could be an indicator that a threat actor has compromised the username and password of this user account and is using it to try and log into the account.\nRef : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins\nThis query has also been updated to include UEBA logs IdentityInfo and BehaviorAnalytics for contextual information around the results. \nPlease note, MFA Failed logons from known IP ranges can be benign depending on the conditional access policies. In case of noisy behavior, consider tuning the source IP ranges or location filter after careful consideration"
}
}
]
Expand Down
Loading
Loading