Getting Data In

Search for account failing a log on at repeating intervals

Communicator

I'm trying to make a search that looks for an account trying to log onto a destination at a repeating interval. This will hopefully cover two potential uses:

  1. Find rogue service accounts with bad passwords or the like repeatedly hitting a location

  2. Find bot activity / slow brute forces due to scripts.

I've been having pretty serious brain-farts this morning, but so far I have this:
index=wineventlog EventCode=4625 Account_Name !="-"| stats count by Account_Name, dest | where count > 1

Which is showing me accounts that have failed authentication multiple times against the same destination. The easy part. Now I need to have them be specific times apart and analyze the trend and that's what's confusing me.

I'm coming to realize that this is more complex that I had originally thought. If I wanted them to be exactly an hour apart that would be less hard (still struggling) but I'm looking for a more generic trend analysis looking for an account having a periodic repeat of any kind.


Edit:

I suppose the big question I have is: "How do I create a search that will run over a period of time and find a trend in the data. Is this username failing to log on to this server at a specific period? What's the period? Is it every hour? Every 227 seconds? Is this even possible?"

0 Karma
1 Solution

SplunkTrust
SplunkTrust

Try something like this...

index=wineventlog EventCode=4625 Account_Name !="-"
| eventstats count as repeatcount by Account_Name, dest 
| where repeatcount > 1
| sort 0 Account_Name, dest, _time
| streamstats current=f last(_time) as priorTime by Account_Name, dest
| eval delay= _time - priorTime
| eventstats avg(delay) as avgdelay stdev(delay) as stdevdelay by Account_Name, dest

Now you have all the events, the time delay between them, and an idea whether the time between them is variable or relatively static.

You could use that universe to identify what "normal" is for standard deviation relative to delay. You could throw out delays that are less than a minute either before or after the above calculations, or calculate it both ways. You could clump them in 5 minute increments either before or after calculating delay. Lots of ways to proceed, but the above strategy should handle your current issue.

View solution in original post

SplunkTrust
SplunkTrust

Try something like this...

index=wineventlog EventCode=4625 Account_Name !="-"
| eventstats count as repeatcount by Account_Name, dest 
| where repeatcount > 1
| sort 0 Account_Name, dest, _time
| streamstats current=f last(_time) as priorTime by Account_Name, dest
| eval delay= _time - priorTime
| eventstats avg(delay) as avgdelay stdev(delay) as stdevdelay by Account_Name, dest

Now you have all the events, the time delay between them, and an idea whether the time between them is variable or relatively static.

You could use that universe to identify what "normal" is for standard deviation relative to delay. You could throw out delays that are less than a minute either before or after the above calculations, or calculate it both ways. You could clump them in 5 minute increments either before or after calculating delay. Lots of ways to proceed, but the above strategy should handle your current issue.

View solution in original post

Communicator

Thank you for the response! From a quick eye test and some tweaking it looks like it's pretty much exactly what I need. Can you confirm I'm reading this correctly? I am also seeing two usernames in one row sometimes. I'm not sure what to make of that.

The below is going to display a table of accounts that are failing to log into the corresponding server with an average standard deviation in time of less than 30 seconds:

index=wineventlog EventCode=4625 Account_Name !="-"
| where NOT LIKE(Account_Name,"%$")
| eventstats count as repeatcount by Account_Name, dest
| where repeatcount > 1
| sort 0 Account_Name, dest, _time
| streamstats current=f last(_time) as priorTime by Account_Name, dest
| eval delay= _time - priorTime
| eventstats avg(delay) as avgdelay stdev(delay) as stdevdelay by Account_Name, dest
| where stdevdelay < 30
| table Account_Name, dest, avgdelay, stdevdelay

0 Karma

SplunkTrust
SplunkTrust

@j4adam. That is correct, there are often two Account_Name fields, due to the structure of windows events.

https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventID=4625

You might find you need to adjust that standard deviation test. 30 seconds stdev is nothing if I try and fail to log on real fast three times in a row... but most installations, 3 is the most that can happen that way, so it wouldn't be quite the kind of thing you are looking for anyway.

0 Karma