Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Password spray attack against Microsoft Entra ID Seamless SSO

Back
Idfb7ca1c9-e14c-40a3-856e-28f3c14ea1ba
RulenamePassword spray attack against Microsoft Entra ID Seamless SSO
DescriptionThis 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.
SeverityMedium
TacticsCredentialAccess
TechniquesT1110
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1h
Query period1h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SeamlessSSOPasswordSpray.yaml
Version1.0.4
Arm templatefb7ca1c9-e14c-40a3-856e-28f3c14ea1ba.json
Deploy To Azure
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])
status: Available
triggerOperator: gt
triggerThreshold: 0
name: Password spray attack against Microsoft Entra ID Seamless SSO
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SeamlessSSOPasswordSpray.yaml
queryPeriod: 1h
severity: Medium
kind: Scheduled
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: UserPrincipalName
    identifier: FullName
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: IPAddress
    identifier: Address
queryFrequency: 1h
relevantTechniques:
- T1110
requiredDataConnectors:
- dataTypes:
  - AADNonInteractiveUserSignInLogs
  connectorId: AzureActiveDirectory
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.'  
tactics:
- CredentialAccess
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])  
id: fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba
version: 1.0.4
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2024-01-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba')]",
      "properties": {
        "alertRuleTemplateName": "fb7ca1c9-e14c-40a3-856e-28f3c14ea1ba",
        "customDetails": null,
        "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.\nMicrosoft Entra ID only logs the requests that matched existing accounts, thus there might have been unlogged requests for non-existing accounts.'\n",
        "displayName": "Password spray attack against Microsoft Entra ID Seamless SSO",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserPrincipalName",
                "identifier": "FullName"
              },
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "IPAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SeamlessSSOPasswordSpray.yaml",
        "query": "let account_threshold = 5;\nAADNonInteractiveUserSignInLogs\n//| where ResultType == \"81016\"\n| where ResultType startswith \"81\"\n| summarize DistinctAccounts = dcount(UserPrincipalName), DistinctAddresses = make_set(IPAddress,100) by ResultType\n| where DistinctAccounts > account_threshold\n| mv-expand IPAddress = DistinctAddresses\n| extend IPAddress = tostring(IPAddress)\n| join kind=leftouter (union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs) on IPAddress\n| summarize\n    StartTime = min(TimeGenerated),\n    EndTime = max(TimeGenerated),\n    UserPrincipalName = make_set(UserPrincipalName,100),\n    UserAgent = make_set(UserAgent,100),\n    ResultDescription = take_any(ResultDescription),\n    ResultSignature = take_any(ResultSignature)\n    by IPAddress, Type, ResultType\n| project Type, StartTime, EndTime, IPAddress, ResultType, ResultDescription, ResultSignature, UserPrincipalName, UserAgent = iff(array_length(UserAgent) == 1, UserAgent[0], UserAgent)\n| extend Name = tostring(split(UserPrincipalName[0],'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName[0],'@',1)[0])\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "PT1H",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess"
        ],
        "techniques": [
          "T1110"
        ],
        "templateVersion": "1.0.4",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}