I currently have two different IDS/IPS systems that are sending data to Splunk. These sensors are spread out across multiple locations and I'd like to be able to generate an alert if one sensor has an X% or Y deviation increase over the previous hour.
The search below does what I want it to for all of my sensors (i.e. comparing the -3 hour count to the -1 hour count), but I want to be able to break it out for each host and not just total count.
(index="ciscoips" OR index="palo") (sourcetype=pan:threat OR sourcetype=cisco:ips*) earliest=-3h@h latest=-1h@h | bin _time span=1h | eval date_hour=strftime(_time, "%H") | stats count AS hits first(date_hour) AS date_hour BY _time | stats avg(hits) BY date_hour
This query shows results such as:
date_hour avg(hits)
11 500
12 343
I would like it to be something along these lines:
host deviation/percentage_diff
sensor1 -5%
sensor2 +12%
sensor3 +50%
Then I would add that to my Enterprise Security correlation rules and trip an alert if a specific sensor broke a threshold of my choosing.
Any help would be greatly appreciated.
Since you are an Enterprise Security user I'd recommend using the Intrusion datamodel - hopefully you've accelerated it. The searches I'll provide use the Intrusion datamodel, but the the concepts will work against the raw data only much slower.
This is something I thought I'd do in the past but hasn't proven to be as useful as I thought. If your environment has very consistent traffic this may be somewhat useful, but new IDS signature or changes to your environment may cause this one to light up, YMMV.
Since you're trying to compare a baseline of 2 hours prior to the most recent hour I've done this using relative time in minutes broken into two searches - one for the most recent hour and one for the two hours prior. The one trick with datamodels is that they won't return any empty results, so I've used timechart, fullnull, and untable to make sure that empty values are accounted for.
| tstats summariesonly=t count as recent_count from datamodel=Intrusion_Detection where earliest=-65m@m latest=-5m@m nodename=IDS_Attacks by IDS_Attacks.dvc, _time span=1h
| rename IDS_Attacks.* as *
| append [| tstats summariesonly=t count from datamodel=Intrusion_Detection where earliest=-185m@m latest=-65m@m nodename=IDS_Attacks by IDS_Attacks.dvc, _time span=1h
| rename IDS_Attacks.* as *
| timechart span=1h limit=0 max(count) as count by dvc
| fillnull value=0
| untable _time, dvc, count
| stats median(count) as hist_median by dvc]
| stats first(recent_count) as recent_count, first(hist_median) as hist_median by dvc
| fillnull value=0 recent_count hist_median
| eval perc_change=case(hist_median=0 and recent_count>0,100,hist_median>0 and recent_count>0,round(100*((recent_count-hist_median)/hist_median)),1==1,0)
| where perc_change>50 or perc_change<-50
| eval perc_change=if(perc_change>0,"+"+tostring(perc_change)+"%",tostring(perc_change)+"%")
| fields dvc recent_count hist_median perc_change
Thanks for the information. I'm going to see if I can slightly modify this and use my index search instead of the data model because in some scenarios I want to be a lot more granular on hosts in X location vs. Y where the data model gives me all of it.
My current workaround is to use the following search and just do it on a per host basis. It's not ideal but it's a start.
ndex="ciscoips" sourcetype="cisco:ips*" earliest=-3h@h latest=-2h@h | stats count as Old | appendcols [search index="ciscoips" sourcetype="cisco:ips*" earliest=-2h@h latest=-1h@h | stats count as New] | eval Percent_Diff = abs(New-Old)/Old*100
I then alert on if Percent_Diff is > X with Enterprise Security.