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 
relevantTechniques:
- T1110.003
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/PasswordSprayingWithMDE.yaml
triggerOperator: gt
kind: Scheduled
entityMappings:
- fieldMappings:
  - columnName: DeviceName
    identifier: FullName
  entityType: Host
- fieldMappings:
  - columnName: IPAddress
    identifier: Address
  entityType: IP
- fieldMappings:
  - columnName: ProcessCommandLine
    identifier: CommandLine
  entityType: Process
requiredDataConnectors:
- dataTypes:
  - DeviceLogonEvents
  connectorId: MicrosoftThreatProtection
queryPeriod: 1d
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   
version: 1.0.0
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.  
tactics:
- CredentialAccess
severity: Medium
name: Password Spraying
queryFrequency: 1d
triggerThreshold: 0
status: Available
id: e00f72ab-fea1-4a31-9ecc-eea6397cd38d
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-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",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess"
        ],
        "techniques": [
          "T1110"
        ],
        "templateVersion": "1.0.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}