Hello community
I am trying to set up a search to catch any succesfull logon after x failed within y minutes. However, I am strugling to see how I would build this search.
Searching for succesful events is easy,
index=<index> status="logged in"
As well is finding unsuccesful events
index=<index> message="Invalid credentials." status="nog logged"
I figured I could do a count by IP-address and/or username for the failed events, but how do I connect the two and add time? I am assuming this should be some combination of "and"/eval/if and where? Just to get a sense of what I am thinking:
index=<index> ... ip-adress WHERE status="logged in" AND (index=<index> message="Invalid credentials." status="nog logged" >3 WHERE delta_time<10min)
What I would like is an output with any ip-adress where any successful logon was perceeded by say 3 failed logons within 10 minutes. I am assuming this will be a large and complex search, at least for me, so any suggestions would really be appreciated.
Best regards
Hi @fatsug , it isn't so hard, you have to create a multiple main search using all the conditions:
index=<index> ((status="logged in" OR (index=<index> message="Invalid credentials." status="nog logged")) earliest=-10m@m latest@m
| eval condition=if(status="logged in","login","logfail")
| stats count(eval(condition="login")) AS login count(eval(condition="logfail")) al logfail BY user
| where logfail>3
Ciao.
Giuseppe
Hi @fatsug , it isn't so hard, you have to create a multiple main search using all the conditions:
index=<index> ((status="logged in" OR (index=<index> message="Invalid credentials." status="nog logged")) earliest=-10m@m latest@m
| eval condition=if(status="logged in","login","logfail")
| stats count(eval(condition="login")) AS login count(eval(condition="logfail")) al logfail BY user
| where logfail>3
Ciao.
Giuseppe
So, this gets me part of the way though not all the way 🙂
index="index" (status="logged in" OR (index="index" message="Invalid credentials." status="not logged")) earliest=-10m@m latest="@m"
| eval condition=if(status="logged in","login","logfail")
| stats count(eval(condition="login")) AS login count(eval(condition="logfail")) AS logfail BY ip
| where logfail > 3
This gives me a nice list with number of failed or successfull logons the last 10 minutes. Though I needed to see if any ip adress attempting "bruteforce" succeeded. To get that number I think this should work:
index="index" (status="logged in" OR (index="index" message="Invalid credentials." status="not logged")) earliest=-10m@m latest="@m"
| eval condition=if(status="logged in","login","logfail")
| stats count(eval(condition="login")) AS login count(eval(condition="logfail")) AS logfail BY ip
| where logfail > 3 AND login > 0
What do you think, this should work right?
Hi @fatsug,
using my search you can detect bruteforce, using your search you can detect a successful bruteforce that's a subset of my search, if you'r searching only successful bruteforce tries your search is the correct one..
If you want a more complete solution, you could filter results using logfail>3, taking all bruteforce tries, and add an eval condition at the end to display the successful tries, something like this:
index="index" (status="logged in" OR (index="index" message="Invalid credentials." status="not logged")) earliest=-10m@m latest="@m"
| eval condition=if(status="logged in","login","logfail")
| stats count(eval(condition="login")) AS login count(eval(condition="logfail")) AS logfail BY ip
| where logfail > 3 AND login > 0
| eval kind=if(login>0,"successful","unsuccessful")
Ciao.
Giuseppe
Hello again@gcusello
Excellent place to start! I'll play around with this and see if I can figure it all out 🙂
Just for my own understanding, what is "al" refering to?
All the best