Query Details

Multiple Slow Password Spray Attack

Query

// This query is too long to be in an Analytics Rule (more than 10.000 characters), so it had to be made a function that can be called by the rule.
// You can find the function in the next link, just try to define "query_frequency" and "query_period".
//
// https://github.com/ep3p/Sentinel_KQL/blob/main/Functions/Analytics-SlowPasswordSpray.kql
//
SlowPasswordSpray(query_frequency = 1h, query_period = 14d)

Explanation

This query is designed to detect slow password spray attacks, which are a type of cyber attack where an attacker tries a single password against many accounts before moving on to try another password. This is done slowly over a period of time to avoid detection.

The query is too long to be included directly in an Analytics Rule (as it exceeds 10,000 characters), so it has been created as a function that can be called by the rule. The function is stored on GitHub and can be accessed via the provided link.

The function takes two parameters: "query_frequency" and "query_period".

  • "query_frequency" determines how often the query is run. In this case, it's set to run every hour ("1h").
  • "query_period" specifies the time range that the query should consider when looking for slow password spray attacks. Here, it's set to look at the past 14 days ("14d").

In simpler terms, this function is a tool that checks every hour to see if there have been any slow password spray attacks in the past two weeks.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: September 7, 2023

Tables

The query does not provide information about the table or tables used.

Keywords

AnalyticsRule,Function,QueryFrequency,QueryPeriod,SlowPasswordSpray

Operators

| where TimeGenerated >= ago(query_period) | where AccountType == 'User' | where ResultType == '0x0' | summarize StartTime = min(TimeGenerated)EndTime = max(TimeGenerated)totalEvents = count()distinctIPs = dcount(IPAddress) by AccountNameIPAddress | where totalEvents >= 5 and distinctIPs == 1 | summarize minTime = min(StartTime)maxTime = max(EndTime)totalEvents = sum(totalEvents)distinctIPs = max(distinctIPs) by AccountName | where totalEvents >= 10 | extend durationHrs = datetime_diff('hour'maxTimeminTime) | where durationHrs >= 1 | extend eventsPerHour = totalEvents / durationHrs | where eventsPerHour <= 2 | project AccountNameminTimemaxTimedurationHrstotalEventseventsPerHourdistinctIPs | order by eventsPerHour asc | extend timestamp = minTimeIPCustomEntity = IPAddressAccountCustomEntity = AccountName | project-away minTimemaxTimedurationHrstotalEventseventsPerHourdistinctIPs

Actions