Pipeline Rule for threat Intelligence (not working)

A couple of months back, we conducted a Purple Teaming exercise and the pipeline rule below was one way we found for detecting an attack.

rule "Attack correlation"

when 
// Type NetworkLogon by Anonymous

has_field("EventID") 
AND
(
contains(to_string($message.EventID), "4624", true) && contains(to_string($message.TargetUserName), "Anonymous", true) && contains(to_string($message.TargetUserName), "Anonymous", true) && has_field ("IpPort") 


OR

//Windows Filtering Platform


contains(to_string($message.EventID), "5156", true) && has_field ("SourcePort")
)
&&

//This checks if the ports are similar
to_string($message.IpPort)==to_string($message.SourcePort)


then

set_field("alert", "1");
end

This is after the first several trials at tweaking it I arrived at this one.

However when we tested, the logs were there but the rule didn’t work, any ideas as to why?
I can’t see any error in the rule’s logic
We are using Graylog 3.1.4 on a Linux 4.9.0-17 debian.

I changed your code in your post using the </> forum tool to make it easier to read… but I still found it hard to read… so I pulled it over to a test Graylog rule page and cleaned it up so it looks like this:

rule "Attack correlation"
when 
// Type NetworkLogon by Anonymous

  has_field("EventID")                                             ||
  (
   contains(to_string($message.EventID), "4624", true)                 && 
   contains(to_string($message.TargetUserName), "Anonymous", true)     && 
   contains(to_string($message.TargetUserName), "Anonymous", true)     && 
   has_field ("IpPort")                                                ||
   contains(to_string($message.EventID), "5156", true)                 && 
   has_field ("SourcePort")
  )                                                                 &&
  //This checks if the ports are similar
  to_string($message.IpPort) == to_string($message.SourcePort)

then
  set_field("alert", "1");
end

The result is actually still not clear with all the AND (&&) and OR (||) operators. You also have the same thing in there twice (TargetUserName). it could stand some logical cleanup and use of parenthesis when changing form ANDs and ORs so its clearer to what you want to happen.

Give it a shot, post the results! :smiley:

1 Like

Sorry, must have added it twice.

when 


has_field("EventID") &&
(

             ( // Type NetworkLogon by Anonymous (eventid 4624 network logon)
			 
     contains(to_string($message.EventID), "4624", true) && 
	 contains(to_string($message.TargetUserName), "Anonymous", true)  && has_field ("IpPort")
				)
 // compares eventid 4624 to 5156
	|| 
			( //Windows Filtering Platform eventid 5156
			contains(to_string($message.EventID), "5156", true) && has_field ("SourcePort")
			)
)
	&&

//This checks if the ports are similar
to_string($message.IpPort)==to_string($message.SourcePort)


then

set_field("alert", "1");
end

First - when you post, code readability is important for the person helping you PLEASE use the </> forum tool and make your code as readable as possible to save me having to copy it out and clean it up to understand it. I pushed the </> on your latest post but the indentation is still wonky so I have to take time to put it together… Simplifying it to:

when 

	has_field("EventID") &&
	(
		( 
			contains(to_string($message.EventID), "4624", true)              && 
			contains(to_string($message.TargetUserName), "Anonymous", true)  && 
			has_field ("IpPort")
		)
																			 || 			 
		( 
			contains(to_string($message.EventID), "5156", true)              && 
			has_field ("SourcePort")
		)
	)                                                                        &&

	to_string($message.IpPort)==to_string($message.SourcePort)                               


then

	set_field("alert", "1");

end

… there is an OR between the IpPort section and and the SourcePort section and later you check to see if IpPort equals SourcePort. So both are required to exist for the rule to be true… I think you can do some reduction there since you can assume if the comparison is true that both fields exist.

Use the debug() feature to find the real values happening in a rule

debug(concat("++++ This is EventID: ", $message.EventID));
debug(concat("++++ This is IpPort: ", $message.IpPort));
debug(concat("++++ This is SourcePort: ", $message.SourcePort));
debug(concat("++++ This is TargetUsername: ", $message.TargetUsername));

(adjust names and wording as needed)

and watch the results in the Graylog Server logs - it will allow you see what your rule is doing and modify…

tail -f /var/log/graylog-server/server.log

1 Like