Password spray attack against Microsoft Entra ID Seamless SSO
| Id | fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba |
| Rulename | Password spray attack against Microsoft Entra ID Seamless SSO |
| Description | This query detects when there is a spike in Microsoft Entra ID Seamless SSO errors. They may not be caused by a Password Spray attack, but the cause of the errors might need to be investigated. Microsoft Entra ID only logs the requests that matched existing accounts, thus there might have been unlogged requests for non-existing accounts. |
| Severity | Medium |
| Tactics | CredentialAccess |
| Techniques | T1110 |
| Required data connectors | AzureActiveDirectory |
| Kind | Scheduled |
| Query frequency | 1h |
| Query period | 1h |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SeamlessSSOPasswordSpray.yaml |
| Version | 1.0.4 |
| Arm template | fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba.json |
let account_threshold = 5;
AADNonInteractiveUserSignInLogs
//| where ResultType == "81016"
| where ResultType startswith "81"
| summarize DistinctAccounts = dcount(UserPrincipalName), DistinctAddresses = make_set(IPAddress,100) by ResultType
| where DistinctAccounts > account_threshold
| mv-expand IPAddress = DistinctAddresses
| extend IPAddress = tostring(IPAddress)
| join kind=leftouter (union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs) on IPAddress
| summarize
StartTime = min(TimeGenerated),
EndTime = max(TimeGenerated),
UserPrincipalName = make_set(UserPrincipalName,100),
UserAgent = make_set(UserAgent,100),
ResultDescription = take_any(ResultDescription),
ResultSignature = take_any(ResultSignature)
by IPAddress, Type, ResultType
| project Type, StartTime, EndTime, IPAddress, ResultType, ResultDescription, ResultSignature, UserPrincipalName, UserAgent = iff(array_length(UserAgent) == 1, UserAgent[0], UserAgent)
| extend Name = tostring(split(UserPrincipalName[0],'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName[0],'@',1)[0])
relevantTechniques:
- T1110
entityMappings:
- fieldMappings:
- columnName: UserPrincipalName
identifier: FullName
- columnName: Name
identifier: Name
- columnName: UPNSuffix
identifier: UPNSuffix
entityType: Account
- fieldMappings:
- columnName: IPAddress
identifier: Address
entityType: IP
triggerThreshold: 0
description: |
'This query detects when there is a spike in Microsoft Entra ID Seamless SSO errors. They may not be caused by a Password Spray attack, but the cause of the errors might need to be investigated.
Microsoft Entra ID only logs the requests that matched existing accounts, thus there might have been unlogged requests for non-existing accounts.'
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AADNonInteractiveUserSignInLogs
triggerOperator: gt
version: 1.0.4
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SeamlessSSOPasswordSpray.yaml
id: fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba
queryFrequency: 1h
query: |
let account_threshold = 5;
AADNonInteractiveUserSignInLogs
//| where ResultType == "81016"
| where ResultType startswith "81"
| summarize DistinctAccounts = dcount(UserPrincipalName), DistinctAddresses = make_set(IPAddress,100) by ResultType
| where DistinctAccounts > account_threshold
| mv-expand IPAddress = DistinctAddresses
| extend IPAddress = tostring(IPAddress)
| join kind=leftouter (union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs) on IPAddress
| summarize
StartTime = min(TimeGenerated),
EndTime = max(TimeGenerated),
UserPrincipalName = make_set(UserPrincipalName,100),
UserAgent = make_set(UserAgent,100),
ResultDescription = take_any(ResultDescription),
ResultSignature = take_any(ResultSignature)
by IPAddress, Type, ResultType
| project Type, StartTime, EndTime, IPAddress, ResultType, ResultDescription, ResultSignature, UserPrincipalName, UserAgent = iff(array_length(UserAgent) == 1, UserAgent[0], UserAgent)
| extend Name = tostring(split(UserPrincipalName[0],'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName[0],'@',1)[0])
severity: Medium
status: Available
queryPeriod: 1h
name: Password spray attack against Microsoft Entra ID Seamless SSO
tactics:
- CredentialAccess
kind: Scheduled