Skip to main content

Hi,
I'm trying to identify failed logins to our Linux servers and created a detection rule for that. Different servers yield slightly different messages that are stored in `metadata.description`. For example, one server would yield the following value:

 

metadata.description = "Failed none for jlxx from 10.0.0.142 port 57835 ssh2"

 


While another server would yield this value:

 

metadata.description = "pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=10.0.0.142 user=jlxx"

 

That's what I put in the `events` section of the rule, to capture both options:

 

events:
$e.metadata.event_type = "STATUS_UPDATE"
$e.metadata.product_event_type = "sshd"
$e.metadata.product_name = "AuditD"
$e.principal.namespace = "LAN"
re.regex($e.metadata.description, `^Failed none for |^pam_unix(sshd:auth): authentication failure;`)

 

But I'm struggling with creating the extraction of the relevant info (user & IP) in the `outcome` section. These lines aren't accepted by the rule editor:

 

$event_source_ip = if(re.regex($e.metadata.description, `^Failed none for`), re.capture($e.metadata.description, `from\\s+([\\d.]+)\\s+port`), re.capture($e.metadata.description, `/rhost=([\\d.]+)\\s{2}user=/gm`))
$event_user = if(re.regex($e.metadata.description, `^Failed none for`), re.capture($e.metadata.description, `for\\s+(\\S+)\\s+from`), re.capture($e.metadata.description, `user=(.*)`))

 

Can anyone help me fix the rule to be able to extract the desire content and assign it to variables that I'd be able to use in the SOAR?

Thank you in advance for your guidance and support

Hi @JuLenny,

I don't have the appropriate data to test, however, please see if the below achieves your use case:

 

rule ayman_test_rule {
meta:
author = "Ayman C"

events:
$e.metadata.event_type = "STATUS_UPDATE"
$e.metadata.product_event_type = "sshd"
$e.metadata.product_name = "AuditD"
$e.principal.namespace = "LAN"
re.regex($e.metadata.description, `^Failed\\snone\\sfor\\s|^pam_unix(sshd:auth):\\sauthentication\\sfailure;`) nocase

$IPaddress = re.capture($e.metadata.description, "from\\\\s([^\\\\s]+)\\\\sport")
$IPaddress = re.capture($e.metadata.description, "rhost=([^\\\\s]+)\\\\suser=")
$User = re.capture($e.metadata.description, "for\\\\s([^\\\\s]+)\\\\sfrom")
$User = re.capture($e.metadata.description, "user=([^\\\\s]+)$")

outcome:

$ExtractedIP = $IPaddress
$ExtractedUser = $User

condition:
$e
}

Kind Regards,

Ayman

 



@AymanC wrote:

$IPaddress = re.capture($e.metadata.description, "from\\\\s([^\\\\s]+)\\\\sport") $IPaddress = re.capture($e.metadata.description, "rhost=([^\\\\s]+)\\\\suser=") $User = re.capture($e.metadata.description, "for\\\\s([^\\\\s]+)\\\\sfrom") $User = re.capture($e.metadata.description, "user=([^\\\\s]+)$")


 

Hi @AymanC 
Thanks for helping out.
Those lines don't work. I only get the alerts of the 1st condition.
I believe there should be an "if" somewhere prior to the assignment of these values.
Regards


Here's another option. I'm making the assumption that the first set of events rows will trigger for both types of events you are looking for. If that is the case, then could we create an option 1 and option 2 for the IP and user respectively.


Then in the the outcome section we could use strings coalesce and return the ip address 1 value if it is non-null and if not return ip address2. Same with user...


 



rule ayman_test_rule {
meta:
author = "Ayman C"
events:
$e.metadata.event_type = "STATUS_UPDATE"
$e.metadata.product_event_type = "sshd"
$e.metadata.product_name = "AuditD"
$e.principal.namespace = "LAN"
re.regex($e.metadata.description, `^Failed\\snone\\sfor\\s|^pam_unix(sshd:auth):\\sauthentication\\sfailure;`) nocase

$IPaddress1
= re.capture($e.metadata.description, "from\\\\s([^\\\\s]+)\\\\sport")
$IPaddress2 = re.capture($e.metadata.description, "rhost=([^\\\\s]+)\\\\suser=")
$User1 = re.capture($e.metadata.description, "for\\\\s([^\\\\s]+)\\\\sfrom")
$User2 = re.capture($e.metadata.description, "user=([^\\\\s]+)$")
outcome:
$ExtractedIP = strings.coalesce($IPaddress1, $IPaddress2)
$ExtractedUser = strings.coalesce($User1, $User2)
condition:
$e
}


Here's another option. I'm making the assumption that the first set of events rows will trigger for both types of events you are looking for. If that is the case, then could we create an option 1 and option 2 for the IP and user respectively.


Then in the the outcome section we could use strings coalesce and return the ip address 1 value if it is non-null and if not return ip address2. Same with user...


 



rule ayman_test_rule {
meta:
author = "Ayman C"
events:
$e.metadata.event_type = "STATUS_UPDATE"
$e.metadata.product_event_type = "sshd"
$e.metadata.product_name = "AuditD"
$e.principal.namespace = "LAN"
re.regex($e.metadata.description, `^Failed\\snone\\sfor\\s|^pam_unix(sshd:auth):\\sauthentication\\sfailure;`) nocase

$IPaddress1
= re.capture($e.metadata.description, "from\\\\s([^\\\\s]+)\\\\sport")
$IPaddress2 = re.capture($e.metadata.description, "rhost=([^\\\\s]+)\\\\suser=")
$User1 = re.capture($e.metadata.description, "for\\\\s([^\\\\s]+)\\\\sfrom")
$User2 = re.capture($e.metadata.description, "user=([^\\\\s]+)$")
outcome:
$ExtractedIP = strings.coalesce($IPaddress1, $IPaddress2)
$ExtractedUser = strings.coalesce($User1, $User2)
condition:
$e
}


Thanks @jstoner 
The "coalesce" function did the trick!


Reply