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

Password Spraying

Back
Ide00f72ab-fea1-4a31-9ecc-eea6397cd38d
RulenamePassword Spraying
DescriptionThis query detects a password spraying attack, where a single machine has performed a large number of failed login attempts, with a large number of different accounts.

For each account, the attacker uses just a few attempts to prevent account lockout. This query uses the DeviceLogonEvents per machine to detect a password spraying attacks.

The machine against which the password spraying is performed (can be DC, a server or even an endpoint) needs to be enrolled in Microsoft Defender for Endpoint.
SeverityMedium
TacticsCredentialAccess
TechniquesT1110.003
Required data connectorsMicrosoftThreatProtection
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/PasswordSprayingWithMDE.yaml
Version1.0.0
Arm templatee00f72ab-fea1-4a31-9ecc-eea6397cd38d.json
Deploy To Azure
let thresholdForUniqueFailedAccounts = 20;
let upperBoundOfFailedLogonsPerAccount = 10;
let ratioSuccessFailedLogons = 0.5;
let timeframe = 1d;
DeviceLogonEvents
| where Timestamp >= ago(timeframe)
| where LogonType != "Unlock" and ActionType in ("LogonSuccess", "LogonFailed")
| where not(isempty( RemoteIP) and isempty( RemoteDeviceName))
| extend LocalLogon=parse_json(AdditionalFields)
| where RemoteIPType != "Loopback"
| summarize SuccessLogonCount = countif(ActionType == "LogonSuccess"), FailedLogonCount = countif(ActionType == "LogonFailed"),
    UniqueAccountFailedLogons=dcountif(AccountName, ActionType == "LogonFailed"), FirstFailed=minif(Timestamp, ActionType == "LogonFailed"),
    LastFailed=maxif(Timestamp, ActionType == "LogonFailed"), LastTimestamp=arg_max(Timestamp, tostring(ReportId)) by RemoteIP, DeviceName // RemoteIP is the source of the logon attempt.
| project-rename IPAddress=RemoteIP
| where UniqueAccountFailedLogons > thresholdForUniqueFailedAccounts and SuccessLogonCount*ratioSuccessFailedLogons < FailedLogonCount and UniqueAccountFailedLogons*upperBoundOfFailedLogonsPerAccount > FailedLogonCount 
status: Available
queryFrequency: 1d
description: |
  This query detects a password spraying attack, where a single machine has performed a large number of failed login attempts, with a large number of different accounts. 
  For each account, the attacker uses just a few attempts to prevent account lockout. This query uses the DeviceLogonEvents per machine to detect a password spraying attacks. 
  The machine against which the password spraying is performed (can be DC, a server or even an endpoint) needs to be enrolled in Microsoft Defender for Endpoint.  
severity: Medium
version: 1.0.0
relevantTechniques:
- T1110.003
name: Password Spraying
triggerThreshold: 0
kind: Scheduled
query: |
  let thresholdForUniqueFailedAccounts = 20;
  let upperBoundOfFailedLogonsPerAccount = 10;
  let ratioSuccessFailedLogons = 0.5;
  let timeframe = 1d;
  DeviceLogonEvents
  | where Timestamp >= ago(timeframe)
  | where LogonType != "Unlock" and ActionType in ("LogonSuccess", "LogonFailed")
  | where not(isempty( RemoteIP) and isempty( RemoteDeviceName))
  | extend LocalLogon=parse_json(AdditionalFields)
  | where RemoteIPType != "Loopback"
  | summarize SuccessLogonCount = countif(ActionType == "LogonSuccess"), FailedLogonCount = countif(ActionType == "LogonFailed"),
      UniqueAccountFailedLogons=dcountif(AccountName, ActionType == "LogonFailed"), FirstFailed=minif(Timestamp, ActionType == "LogonFailed"),
      LastFailed=maxif(Timestamp, ActionType == "LogonFailed"), LastTimestamp=arg_max(Timestamp, tostring(ReportId)) by RemoteIP, DeviceName // RemoteIP is the source of the logon attempt.
  | project-rename IPAddress=RemoteIP
  | where UniqueAccountFailedLogons > thresholdForUniqueFailedAccounts and SuccessLogonCount*ratioSuccessFailedLogons < FailedLogonCount and UniqueAccountFailedLogons*upperBoundOfFailedLogonsPerAccount > FailedLogonCount   
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/PasswordSprayingWithMDE.yaml
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
  dataTypes:
  - DeviceLogonEvents
tactics:
- CredentialAccess
id: e00f72ab-fea1-4a31-9ecc-eea6397cd38d
queryPeriod: 1d
entityMappings:
- fieldMappings:
  - columnName: DeviceName
    identifier: FullName
  entityType: Host
- fieldMappings:
  - columnName: IPAddress
    identifier: Address
  entityType: IP
- fieldMappings:
  - columnName: ProcessCommandLine
    identifier: CommandLine
  entityType: Process
{
  "$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/e00f72ab-fea1-4a31-9ecc-eea6397cd38d')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/e00f72ab-fea1-4a31-9ecc-eea6397cd38d')]",
      "properties": {
        "alertRuleTemplateName": "e00f72ab-fea1-4a31-9ecc-eea6397cd38d",
        "customDetails": null,
        "description": "This query detects a password spraying attack, where a single machine has performed a large number of failed login attempts, with a large number of different accounts. \nFor each account, the attacker uses just a few attempts to prevent account lockout. This query uses the DeviceLogonEvents per machine to detect a password spraying attacks. \nThe machine against which the password spraying is performed (can be DC, a server or even an endpoint) needs to be enrolled in Microsoft Defender for Endpoint.\n",
        "displayName": "Password Spraying",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DeviceName",
                "identifier": "FullName"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "IPAddress",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "Process",
            "fieldMappings": [
              {
                "columnName": "ProcessCommandLine",
                "identifier": "CommandLine"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/PasswordSprayingWithMDE.yaml",
        "query": "let thresholdForUniqueFailedAccounts = 20;\nlet upperBoundOfFailedLogonsPerAccount = 10;\nlet ratioSuccessFailedLogons = 0.5;\nlet timeframe = 1d;\nDeviceLogonEvents\n| where Timestamp >= ago(timeframe)\n| where LogonType != \"Unlock\" and ActionType in (\"LogonSuccess\", \"LogonFailed\")\n| where not(isempty( RemoteIP) and isempty( RemoteDeviceName))\n| extend LocalLogon=parse_json(AdditionalFields)\n| where RemoteIPType != \"Loopback\"\n| summarize SuccessLogonCount = countif(ActionType == \"LogonSuccess\"), FailedLogonCount = countif(ActionType == \"LogonFailed\"),\n    UniqueAccountFailedLogons=dcountif(AccountName, ActionType == \"LogonFailed\"), FirstFailed=minif(Timestamp, ActionType == \"LogonFailed\"),\n    LastFailed=maxif(Timestamp, ActionType == \"LogonFailed\"), LastTimestamp=arg_max(Timestamp, tostring(ReportId)) by RemoteIP, DeviceName // RemoteIP is the source of the logon attempt.\n| project-rename IPAddress=RemoteIP\n| where UniqueAccountFailedLogons > thresholdForUniqueFailedAccounts and SuccessLogonCount*ratioSuccessFailedLogons < FailedLogonCount and UniqueAccountFailedLogons*upperBoundOfFailedLogonsPerAccount > FailedLogonCount \n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [
          "T1110.003"
        ],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess"
        ],
        "techniques": [
          "T1110"
        ],
        "templateVersion": "1.0.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}