Detect Password Spray Attempts
Description
This analytic employs the 3-sigma approach to detect an unusual volume of failed authentication attempts from a single source. A password spray attack is a type of brute force attack where an attacker tries a few common passwords across many different accounts to avoid detection and account lockouts. By utilizing the Authentication Data Model, this detection is effective for all CIM-mapped authentication events, providing comprehensive coverage and enhancing security against these attacks.
Query · spl
| tstats `security_content_summariesonly` values(Authentication.user) AS unique_user_names dc(Authentication.user) AS unique_accounts values(Authentication.app) as app count(Authentication.user) as total_failures from datamodel=Authentication.Authentication where Authentication.action="failure" NOT Authentication.src IN ("-","unknown") by Authentication.action Authentication.app Authentication.authentication_method Authentication.dest
Authentication.signature Authentication.signature_id Authentication.src sourcetype _time span=5m
| `drop_dm_object_name("Authentication")`
```fill out time buckets for 0-count events during entire search length```
| appendpipe [| timechart limit=0 span=5m count | table _time] | fillnull value=0 unique_accounts
``` Create aggregation field & apply to all null events```
| eval counter=src+"__"+sourcetype+"__"+signature_id | eventstats values(counter) as fnscounter | eval counter=coalesce(counter,fnscounter)
``` stats version of mvexpand ```
| stats values(app) as app values(unique_user_names) as unique_user_names values(total_failures) as total_failures values(src) as src values(signature_id) as signature_id values(sourcetype) as sourcetype count by counter unique_accounts _time
``` remove duplicate time buckets for each unique source```
| sort - _time unique_accounts | dedup _time counter
```Find the outliers```
| eventstats avg(unique_accounts) as comp_avg , stdev(unique_accounts) as comp_std by counter | eval upperBound=(comp_avg+comp_std*3) | eval isOutlier=if(unique_accounts > 30 and unique_accounts >= upperBound, 1, 0) | replace "::ffff:*" with * in src | where isOutlier=1 | foreach *
[ eval <<FIELD>> = if(<<FIELD>>="null",null(),<<FIELD>>)]
| table _time, src, action, app, unique_accounts, unique_user_names, total_failures, sourcetype, signature_id, counter | `detect_password_spray_attempts_filter`
Implementation guide
Ensure in-scope authentication data is CIM mapped and the src field is populated with the source device. Also ensure fill_nullvalue is set within the macro security_content_summariesonly. This search opporates best on a 5 minute schedule, looking back over the past 70 minutes. Configure 70 minute throttling on the two fields _time and counter.
Known false positives
- No false positives have been identified at this time.
Analyst notes
Known false positives: No false positives have been identified at this time.