Query Details
id: dfe51b81-efb9-45bd-abbc-ee8ee34d15b1
name: Unusual Azure AD Conditional Access Failures after Policy Change
description: |
'Uses Behaviour Analytics (UEBA) information and Azure AD Audit Log in Microsoft Sentinel and correlates unusual numbers of Conditional Access failures with sign-in logs. The result will be used for correlation to detect CA policy changes in AuditLogs within the time range.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- BehaviorAnalytics
- AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- Persistence
relevantTechniques:
- T1078
- T1098
query: |
BehaviorAnalytics
| where ActivityInsights.UnusualNumberOfAADConditionalAccessFailures == "True"
| extend UserPrincipalName = tolower(UserPrincipalName)
| join kind=inner (
union SigninLogs, AADNonInteractiveUserSignInLogs
| where ConditionalAccessStatus == "failure"
| mv-expand ConditionalAccessPolicies_dynamic
| extend ConditionalAccessResult = parse_json(ConditionalAccessPolicies_dynamic.result)
| extend ConditionalAccessName = parse_json(ConditionalAccessPolicies_dynamic.displayName)
| extend ConditionalAccessId = parse_json(ConditionalAccessPolicies_dynamic.id)
| extend ConditionalAccessEnforcedControl = parse_json(tostring(ConditionalAccessPolicies_dynamic.enforcedGrantControls))
| extend SourceIPAddress = IPAddress
| extend UserPrincipalName = tolower(UserPrincipalName)
| where ConditionalAccessResult == "failure"
| distinct CorrelationId, UserDisplayName, UserPrincipalName, SourceIPAddress, tostring(ConditionalAccessName), tostring(ConditionalAccessId), tostring(ConditionalAccessResult), tostring(ConditionalAccessEnforcedControl), ResultType, AADTenantId
) on UserPrincipalName, SourceIPAddress
| summarize count() by ConditionalAccessName, ConditionalAccessId, ResultType, AADTenantId
| join kind=inner (
AuditLogs
| where OperationName == "Update conditional access policy"
| extend ConditionalAccessId = tostring(TargetResources[0].id)
) on ConditionalAccessId
| extend Actor = parse_json(tostring(InitiatedBy.user)).userPrincipalName
| project TimeGenerated, OperationName, Actor, ConditionalAccessName, CorrelationId, ResultType, count_
| extend AccountCustomEntity = Actor
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: AccountCustomEntity
version: 1.1.0
This query is designed to detect unusual numbers of Azure AD Conditional Access failures after a policy change. It uses Behavior Analytics and Azure AD Audit Log data in Microsoft Sentinel to correlate the failures with sign-in logs. The query checks for any unusual number of failures and then joins the relevant information from the sign-in logs and audit logs. The result is a summary of the count of failures for each conditional access policy that has been updated. The query is run once a day and has a medium severity level. The relevant techniques for this query are Initial Access and Persistence.

Thomas Naunheim
Released: August 23, 2023
Tables
Keywords
Operators