Detection rules › Kusto

Password Spray

Author
Cyb3rMonk
Source
github.com/Cyb3r-Monk/Threat-Hunting-and-Detection

Below queries detect password spray attacks using sliding window count plugin. Because of implementation of the sliding window, queries work better than the bin() usage, but may create duplicate alerts. Grouping can be used in such cases. Sentinel Query:

MITRE ATT&CK coverage

TacticTechniques
Credential AccessNo specific technique

References

Telemetry coverage

Rule body

// Author       : Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
//
// Link to original post:
// https://posts.bluraven.io/advanced-kql-for-threat-hunting-window-functions-part-2-dce3e321f54b
//
// Description  : Detect if there are more than 2 distinct users seen from the same IP in a 3h window.
//
// Query parameters:
//
let start = ago(12h);
let end = now();
let lookbackWindow = 3h;
let bin = 1h;
let threshold = 2;
SecurityEvent
| where EventID in (4624, 4625)
| where IpAddress !in ("127.0.0.1", "::1", "-")
| evaluate sliding_window_counts(TargetUserName, TimeGenerated, start, end, lookbackWindow, bin, IpAddress)
| sort by IpAddress, TimeGenerated asc
| where Dcount >= 2

// Author       : Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
//
// Link to original post:
// https://posts.bluraven.io/advanced-kql-for-threat-hunting-window-functions-part-2-dce3e321f54b
//
// Description  : Detect if there are more than 2 distinct users seen from the same IP in a 3h window.
//
// Query parameters:
//
let start = ago(12h);
let end = now();
let lookbackWindow = 3h;
let bin = 1h;
let threshold = 2;
DeviceLogonEvents
| where Timestamp > ago(lookbackWindow)
| where RemoteIP !in ("127.0.0.1","::1","-") and isnotempty(RemoteIP)
| evaluate sliding_window_counts(AccountName, Timestamp, start, end, lookbackWindow, bin, RemoteIP)
| where Dcount > threshold

Stages and Predicates

Parameters

let start = ago(12h);
let end = now();
let lookbackWindow = 3h;
let bin = 1h;
let threshold = 2;

Stage 1: source

SecurityEvent

Stage 2: where

where EventID in~ (4624, 4625)

Stage 3: where

where not (IpAddress in~ ("-", "127.0.0.1", "::1"))

Stage 4: evaluate

evaluate

Stage 5: sort

sort by IpAddress, TimeGenerated

Stage 6: where

where Dcount >= 2

Stage 7: source

DeviceLogonEvents

Stage 8: where

where Timestamp > ago(10800s)

Stage 9: where

where not (RemoteIP in~ ("-", "127.0.0.1", "::1")) and isnotempty(RemoteIP)

Stage 10: evaluate

evaluate

Stage 11: where

where Dcount > 2

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Dcountge
  • 2
field:"Dcount" kind:ge value:"2"
Dcountgt
  • 2
field:"Dcount" kind:gt value:"2"
EventIDin
  • 4624 corpus 29 (splunk 13, kusto 11, chronicle 4, elastic 1)
  • 4625 corpus 15 (splunk 11, chronicle 2, kusto 2)
field:"EventID" kind:in
RemoteIPis_not_null
  • (no value, null check)
field:"dest_ip" kind:is_not_null