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