text code block:| tstats `security_content_summariesonly` dc(Authentication.user) AS unique_accounts dc(Authentication.src) as unique_src values(Authentication.app) as app values(Authentication.src) as src count(Authentication.user) as total_failures from datamodel=Authentication.Authentication where Authentication.action="failure" NOT Authentication.src IN ("-","unknown") Authentication.user_agent="*" by Authentication.signature_id, Authentication.user_agent, sourcetype, _time span=10m | `drop_dm_object_name("Authentication")` ```fill out time buckets for 0-count events during entire search length``` | appendpipe [| timechart limit=0 span=10m count | table _time] | fillnull value=0 unique_accounts, unique_src ``` Create aggregation field & apply to all null events``` | eval counter=sourcetype+"__"+signature_id | eventstats values(counter) as fnscounter | eval counter=coalesce(counter,fnscounter) | stats values(total_failures) as total_failures values(signature_id) as signature_id values(src) as src values(sourcetype) as sourcetype values(app) as app count by counter unique_accounts unique_src user_agent _time ``` remove 0 count rows where counter has data``` | sort - _time unique_accounts | dedup _time counter ``` 3-sigma detection logic ``` | eventstats avg(unique_accounts) as comp_avg_user , stdev(unique_accounts) as comp_std_user avg(unique_src) as comp_avg_src , stdev(unique_src) as comp_std_src by counter user_agent | eval upperBoundUser=(comp_avg_user+comp_std_user*3), upperBoundsrc=(comp_avg_src+comp_std_src*3) | eval isOutlier=if((unique_accounts > 30 and unique_accounts >= upperBoundUser) and (unique_src > 30 and unique_src >= upperBoundsrc), 1, 0) | replace "::ffff:*" with * in src | where isOutlier=1 | foreach * [ eval <<FIELD>> = if(<<FIELD>>="null",null(),<<FIELD>>)] | mvexpand src | iplocation src | table _time, unique_src, unique_accounts, total_failures, sourcetype, signature_id, user_agent, src, Country | eval date_wday=strftime(_time,"%a"), date_hour=strftime(_time,"%H") | `detect_distributed_password_spray_attempts_filter`
View this rule on Splunk
This rule was sourced from the official Splunk public repository. View the original rule on GitHub(external, opens in a new tab or window).