min-width: mobile
min-width: 400px
min-width: 550px
min-width: 750px
min-width: 1000px
min-width: 1200px
NOTICE We have updated our Privacy Policy to include GDPR and the use of cookies. Click "Accept" to continue. ACCEPT

Blog

Using Jack Crook’s log analysis concepts with Sagan

Posted by Champ Clark on January 07, 2018

* Note:  This blog was updated Jan 30th, 2018.   We've updated some of the rules after testing in produciton enviroments.  Rules that do not have updates are considered stable and already providing value. 

Several months ago I started following a fellow "log junkie" on Twitter named Jack Crook (Twitter: @jackcr).  He writes a great blog called "DFIR and Threat Hunting" in which he discusses methods and techniques he uses to "find bad guys" in networks.  He recently wrote a blog called "A Few of My Favorite Things - Continued"

It's a great read full of useful tips.

Jack Crook uses Splunk and recently the ELK stack for threat “hunting”.   At Quadrant,  we also use Elasticsearch in similar methods Jack describes in his blog,  but I wanted to take this opportunity to see if I could mimic his work with Sagan!

For those of you not familiar with Sagan,  it works quite differently than Splunk or ELK.  Those tools are really good at correlating historical data.  Sagan works differently.  What Sagan does is to provide you with an early warning system.  Sagan treats logs like IDS treats network packets.  That is,  Sagan monitors and alerts in real time.  Sagan keeps track of historical events in the form of "xbits".   Sagan “xbits” work similar to how Suricata’s xbits work.   It’s an extension of Snort’s “flowbit” idea and it's a way for Sagan to "flag" certain logs or events for correlation at a later time.

Don't be confused by the signatures within the post.  While they may look like Cisco Snort or Suricata rules,  they are actually Sagan rules.  We purposely made Sagan rules resemble Snort rules for various reasons.   The primary reason is that it is a signature syntax security professionals are familiar with and have tools to manage.

The Sagan engine is an open source (GPLv2) project.   To learn more about Sagan,   I invite you to check out the Sagan website (http://sagan.io)

We use Nxlog (https://nxlog.co) to collect data from Windows systems.

1.  "4624 Type 3 Logon"

"As adversaries move around your network they will often use built in windows tools for this, such as net commands.  These commands will generate a 4624 Type 3 network logon.  Attackers will also likely stray from normal logon patterns within your environment.  Logon times, users and src/dest combinations may look different.  By looking for rare combinations where there is a remote IP address you may be able to reduce some of the noise while still identifying those events that should be investigated"

The first one to start with is pretty straight forward.  I like the "Keep It Simple Stupid" (KISS) model.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Suspicious network login"; program: *Security*; content: " 4624|3a| "; content: "Logon Type|3a| 3"; pcre: "/^((?!Account Name: (.*)\$ ).)*$/"; content:!"Workstation Name|3a| Source Network Address|3a|"; reference: url,indingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033416; sid:50033416; classtype:suspicious-login; rev:1;)

One thing I’d like to point out is Sagan already has rules to monitor Windows event 4624 in its stock rule sets.   For example,  we monitor 4624 for GeoIP login location,  time based events and "threat intel" IP address via Bluedot & Bro-Intel (Critical Stack, etc).

Here are links to those Sagan rule sets.

https://github.com/beave/sagan-rules/blob/master/windows-geoip.rules

https://github.com/beave/sagan-rules/blob/master/windows-aetas.rules

https://github.com/beave/sagan-rules/blob/master/windows-bluedot.rules

https://github.com/beave/sagan-rules/blob/master/windows-brointel.rules

I went ahead and created one more rule that I thought might be useful.  This one watches for Windows event 4624 like above but only fires when the "Source Network Address" is _not_ RFC1918.  I’m using Sagan’s “meta_content” option to determine the “Source Address”.  There’s probably a better way to do this via PCRE.  However,  “meta_content” has less “baggage” than PCRE.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Suspicious network login from non-RFC1918"; program: *Security*; content: " 4624|3a| "; content: "Logon Type|3a| 3"; parse_src_ip: 1; meta_content:!"Source Network Address|3a| %sagan%",10.,192.168.,-,|3a 3a|1,127.0.0.1,172.16.,172.17.,172.18.,172.19.,172.20.,172.21.,172.22.,172.23.,172.24.,172.25.,172.26.,172.27.,172.28.,172.29.,172.30.,172.31.; meta_nocase; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033417; sid:50033417; classtype:suspicious-login; rev:2;)

[Update: This is revision 2 of this rule.  In the latest github.com/beave/sagan code the was a bug in the meta_content:! .  Thanks to this rule,  it was identified and resolved.   Previously meta_content did not support hex/pipe content.  We wanted to avoid ::1 so hex/pipe content was added to meta_content.   Since these changes,  this rule has been solid] ​

2. Command line with ip

"If you have command line process audit logging within your environment it may be useful to determine how your admins administer remote machines.  Do they typically connect to them by IP address or hostname.  By knowing what is normal within your network, it is much easier to develop queries that will surface the abnormal."

If you're running Microsoft Sysmon,  and you should be,  this one is straight forward.  This is a useful rule that looks for IP address within a command line.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] SYSMON command line IP detected"; content: " 1|3a| "; pcre: "/CommandLine: (.*)([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/"; classtype: suspicious-command; program: *Sysmon*; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033418; sid:50033418; rev:2;)

[Update:  All Sysmon rules worked well.  We had to make a minor change from "program: Sysmon;" to "program: *Sysmon*;" due to logging changes.  Other than that,  these rules are solid.]

 

3. C$ share identified in command line

"Using windows shares is an easy way for an attacker to move data around.  Whether it's tools that have been brought in, or data intended for exfiltration.  Pay attention to machines and users accessing hidden shares.  Is this a rare occurrence for this machine/user or combination of both?  Also pay attention to the process responsible for accessing the share and what the action is."

This one is straight forward and requires Sysmon as well.  

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] SYSMON command line $\\ type request"; content: " 1|3a| "; pcre: "/CommandLine: (.*)\$\\\\(.*)/"; classtype: suspicious-command; program: *Sysmon*; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033419; sid:50033419; rev:2;)

4.  HTTP request via powershell

"This goes along with knowing your environment.  Is it normal for powershell to invoke a web request?  If the answer is yes, are the destinations unique?  By looking for unique destinations that were the result of powershell invoking a web request you have a high likelihood of spotting a malicious command."

I can see this leading to some false positive.  As Mr. Crook says knowing your environment is key.   In the real world,  you might want to “tweek” this rule.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] SYSMON command line $\\ type request"; content: " 1|3a| "; pcre: "/CommandLine: (.*):\/\/(.*)/"; pcre: "/Image: (.*)powershell\.exe(.*)/i"; classtype: suspicious-command; program: *Sysmon*; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033420; sid:50033420; rev:2;)

5.  Data movement dest to source

"The above query will try to identify 3 logs with event id's 5145 and an access mask of either 0x100180, 0x80 or 0x130197 and all generated within the same second.  This would be indicative of a file being copied to a $ share from a command prompt.  Unfortunately, after banging my head against a wall for an entire weekend, I have not found a way to do this with Kibana or Elasticsearch."

This is an interesting rule which allows me explain how xbits work within Sagan.  While the following signatures appear to be almost identical,  the first checks for an xbit via "isset" and the second rules "sets" an xbit for one second.  This might seem backwards but it is not.

At run time,  Sagan loads rules in the order they are in the .rules file.  There is no reordering in memory via signature ID (sid).  This allows you to control how Sagan "see's" rule and what order they get processed.  We take advantage of this to detect if an event has happened two or more times.

Both rules look for the "Object Type" of "File".  The "Share Name" needs to have a $ at the end.  We use the Sagan "meta_content" to look for the "Access Mask" Jack describes.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Suspicious file copy to a share"; program: *Security*; content: " 5145|3a| "; content: "Object Type|3a| File"; pcre: "/Share Name: (.*)\$ /"; meta_content: "Access Mask|3a| %sagan%",0x100180,0x80,0x130197; xbits: isset,by_src,dst_src_suscopy; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033412; sid:50033412; classtype:misc-attack; rev:1;)

We check to see if the xbit has been set for this host.  The "host" will default to the system IP address sending logs.  If this is the first pass of this type of event, the rule above will not fire because the xbit has not had a chance to be set.  However,  if the xbit is set, we know this event has happened in the past and need to fire the signature.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Suspicious file copy to a share [XBIT SET]"; program: *Security*; content: " 5145|3a| "; content: "Object Type|3a| File"; pcre: "/Share Name: (.*)\$ /"; meta_content: "Access Mask|3a| %sagan%",0x100180,0x80,0x130197; xbits: set,dst_src_suscopy,1; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033413; sid:50033413; classtype:misc-attack; rev:1;)

 

5a. Data movement source to destination.

To look at data moving the other direction,  we essentially use the same rule but with different "Access Masks". This rule does this xbit check (isset)......

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Suspicious file copy to a share"; program: *Security*; content: " 5145|3a| "; content: "Object Type|3a| File"; pcre: "/Share Name: (.*)\$ /"; meta_content: "Access Mask|3a| %sagan%",0x100181,0x80,0x120089; xbits: isset,none,src_dst_suscopy;reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033414; sid:50033414; classtype:misc-attack; rev:1;)

This rule does the "set".....

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Suspicious file copy to a share [XBIT SET]"; program: *Security*; content: " 5145|3a| "; content: "Object Type|3a| File"; pcre: "/Share Name: (.*)\$ /"; meta_content: "Access Mask|3a| %sagan%",0x100181,0x80,0x120089; xbits: set,src_dst_suscopy,1; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033415; sid:50033415; classtype:misc-attack; rev:1;)

[Update: No modifications to this rule.  We have noticed that in production it triggers on valid file movement.    As Jack repeatedly points out,  knowing your environment is important!  In the cases we've seen this fire off,  it has been easy enough to write excluding meta_content:! rule options]

6.   Remote WMIC

"Execution is an attacker need.  We've already said that attackers will often use windows tools when moving laterally within your network and wmic can be a method that an attacker can use to execute commands on a remote machine.  Pay attention to source/dest/user combinations and the processes that are spawned on the remote machine.  This query is intended to identify the processes that are spawned within 1 second of wmiprvse executing on the destination side of the wmic command.  This query will also attempt to identify the source of the wmic connection."

Like last time,  we’ll use xbit’s to track events.

The first rule sets a xbit named "wmiprvse" for one second if Sagan see's the Windows event 4688 with a process name of "wmiprvse.exe".  You might have noticed the "xbit: nounified2" option.  This option tells Sagan to not write out a unified2 event when this signature is triggered.  This way,  we won’t create an “alert” that our SOC would have to investigate.  It does not stop Sagan from writing out it’s fast.log, alert.log, etc.   We can use those logs to help debug Sagan xbits.

If we were really bold,  we could pass the "noalert" option which wouldn't generate any indication that the signature has tripped.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] wmiprvse.exe [XBIT SET]"; content: " 4688|3a| "; pcre: "/Process Name: (.*)wmiprvse\.exe(.*)/i"; xbits: set,wmiprvse,1; xbits:nounified2; classtype: suspicious-command; program: *Security*; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033421; sid:50033421; rev:1;)

The next rule checks for Windows event ID 4624 and if the “wmiprvse” xbit is set.  If it is,  this signature will fire and our SOC will be alerted.  Keep in mind,  the xbit expires within one second.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Possible remote WMIC command"; program: *Security*; content: " 4624|3a| "; content: "Logon Type|3a| 3"; content:!"Source Network Address|3a| -"; xbits: isset,src_xbitdst,wmiprvse; parse_src_ip: 1; parse_port; sid:50033422; classtype:suspicious-login; rev:2;)

[Update:  This rule has been incredibly useful.   This revision changes the xbit detection direction to "src_xbitdst".   The first rule sets an xbit of the source when the wmiprvse.exe command is executed.  The "src_xbitdst" matches if the source is the machine executing the command.  This rule has a low false positive rate.  However,  if you are using Solarwinds or other utilities that query WMI,  we'll want to create a "white list" to exclude these.   Once you create a white list you'll only be alerted on "new" systems quering WMI!]

6 WMIC 4648 login

"Execution is an attacker need.  We've already said that attackers will often use windows tools when moving laterally within your network and wmic can be a method that an attacker can use to execute commands on a remote machine.  By monitoring explicit logons you can identify users, machines and processes that were used which resulted in an authentication to a remote machine.  This query watches for processes that may often be used during lateral movement."

This one is straight forward.   We monitor for “Account Name: -”,  the “Target Server Name” is not “localhost” and if the process is “net.exe”, “wmic.exe” or “powershell.exe”.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] WMIC 4648 login"; program: *Security*; content: " 4648|3a| "; content:!"Account Name|3a| -"; content:!"Target Server Name|3a| localhost"; pcre: "/Target Server Name: (.*)\$ /"; pcre: "/Process Name: (.*)(net\.exe|wmic\.exe|powershell\.exe)(.*)/i"; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033423; sid:50033423; classtype:misc-attack; rev:1;)

7. Process spawned from cmd.exe

"Cmd.exe is probably the most executed process by an attacker during KC7.  Monitor child processes and identify those clusters that may be related to malicious execution."

I like this one.  Nice and simple but requires you to be running Sysmon.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] SYSMON Possible CMD detected"; content: " 1|3a| "; pcre: "/CommandLine: (.*)cmd(.*)/i"; classtype: suspicious-command; program: *Sysmon*; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033424; sid:50033424; rev:2;)

[Update:  This is a good rule but can be noisy if you have administrators firing up command shells.   Might be best to create an $ADMIN_CMD variable in the sagan.yaml configration and meta_content:! them.  This way,   the signauter won't fire on your administrators and only on "new" cmd.exe being started].

8.  Mounting remote $ share

“Using windows shares is an easy way for an attacker to move data around.  Whether it’s tools that have been brought in, or data intended for exfiltration.  Pay attention to machines and users accessing hidden shares.  Is this a rare occurrence for this machine/user or combination of both?”

This one required some pcre foo and was a lot of fun to write!  In this case,  we want the signature to trigger when Windows event ID 5140 happens and the "Account Name" does NOT contain a "$" at the end.  For example, "Account Name: CHAMP" should trigger but the signature should ignore "Account Name: CHAMP$".  We look for "Share Names" that have a trailing $.

In Jack's blog,  you'll notice is says "Access_Mask=0x1".  I could not locate a log entry that had this "Access Mask",  so I skipped it.   I’ll have to ask Mr. Crook about that later.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg: "[JACKCR] Mount of a $ share"; program: *Security*; content: " 5140|3a| "; pcre: "/^((?!Account Name: (.*)\$ ).)*$/"; pcre: "/Share Name: (.*)\$/"; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033425; sid:50033425; classtype:misc-attack; rev:1;)

9. Possible credential dumper execution

"Attackers need credentials if they are going to move laterally.  Identifying the potential execution of a credential dumper is important as they can often be missed by AV.  This query looks at the loading of dll's by process and identifies those that have the clusters often used together by various credential dumping tools."

The idea here is to detect via Sysmon when an "image" loads 2 or more Windows .DLL's that might be related to a credential dumper.  It's an interesting concept and I like the idea.  Like the rule in #5,  we’ll be using “xbits” to correlate events within one second.  The first rule checks for the xbit “creddump”.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] SYSMON Possible credential dumper execution"; content: " 1|3a| "; pcre: "/ImageLoad: (.*)(wdigest\.dll|kerberos\.dll|tspkg\.dll|sspicli\.dll|samsrv\.dll|secur32\.dll|samlib\.dll|wlanapi\.dll|vaultcli\.dll|cypt32\.dll|cryptdll\.dll|netapi\.dll|netlogon\.dll|msv1_0\.dll)(.*)/i"; program: *Sysmon*; xbits: isset,by_src,creddump; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033426; classtype: suspicious-command; sid:50033426; rev:1;)

The next rule “sets” the xbit “creddump”.

alert any $EXTERNAL_NET any -> $HOME_NET any (msg:"[JACKCR] SYSMON Possible credential dumper execution"; content: " 1|3a| "; pcre: "/ImageLoad: (.*)(wdigest\.dll|kerberos\.dll|tspkg\.dll|sspicli\.dll|samsrv\.dll|secur32\.dll|samlib\.dll|wlanapi\.dll|vaultcli\.dll|cypt32\.dll|cryptdll\.dll|netapi\.dll|netlogon\.dll|msv1_0\.dll)(.*)/i"; program: *Sysmon*; xbits: set,creddump,1; xbit: nounified2; reference: url,findingbad.blogspot.cz/2017/12/a-few-of-my-favorite-things-continued.html; reference: url,wiki.quadrantsec.com/bin/view/Main/50033427; classtype: suspicious-command; sid:50033427; rev:1;)

Under signature ID 50033426,  we have this rule (50033427).  During the "set", we use the xbit "nounified2" option again.  We don't want this rule to fire off an "alert".  We want it to mark the first time a image/DLL has been loaded of interest.   Since the xbit is not set,  if we see this event happen _again_,  then 50033426 will fire.  Then our SOC can start investigation into the process.

Conclusion:

This was a very fun exercise!  If you don't already read Jack Crooks blog, you should.  It's an excellent resource.  The Sagan signatures in this article were created on a lab machine and seem to work well.  They have not been tested "out in the field" yet.  Keep your eye on this post as I'll be updating it as field testing starts. 

Keep in mind,  data sharing goes both directions.  In Sagan,  we have thousands and thousands of signatures.  Feel free to convert them for your use too! 

Update 2018/01/30

After extensive testing and some minor modifications,  Quadrant will be adding these rules into the standard Sagan rule set!   Jack Crook has done an excellent job and these rules will help people with early detection of hostile actors within there network.  When the rules are offically added,  we'll modify this page.   

Edit:2018/01/30 - Update information.

Edit:2018/01/08 - Minor spelling/grammar edits.  Thanks Jeremy! 

Posted in Announcements