New to Chronicle: Single event rules

This is the second post from Google Cloud Principal Security Strategist John Stoner as part of his deep-dive "New to Chronicle" series, which helps propel forward security teams either new to SIEM or replacing their SIEM with Chronicle.

The rules engine is a fundamental component of Chronicle. Ingesting and searching data is important, but if you cannot generate detection events, analysts are left with petabytes of data to search through without a specific focus or prioritization.

Our goal today is to introduce you to Chronicle’s rules engine and explore the capabilities it provides. This blog post is the tip of the iceberg in regard to the rules engine. Subsequent posts will go deeper into the engine so if you don’t see exactly what you are looking for today, don’t worry, there is more to come!

The rules engine in Chronicle uses a language called YARA-L to build detections. For those not familiar with YARA, it is the language that Google’s VirusTotal team developed for use with malware samples. The concepts of YARA have been adapted to focus on logs and its associated telemetry, and we call it YARA-L.

YARA-L can be used for detection as events are being ingested and it can be used to look retrospectively across historical data. This provides analysts with flexibility to develop new detections and use historical data to validate and test rules, as well as uncover threats that were not previously known. If you want to learn more about YARA-L, check out this whitepaper.

YARA-L has a fixed format of sections used when creating rules. While there are six sections as of today, only three are required to get started. Let's focus just on the components needed to write a single event rule. In future posts, we will cover the additional areas as we build increasingly robust rules.

The three required sections of any YARA-L rule are the meta, events, and condition sections.

  • Meta contains the metadata associated with the rule itself.

  • Events contain the UDM fields and their associated values that are being evaluated to determine if criteria exist for the rule to fire.

  • Condition specifies the circumstances that would cause the rule to fire. (Spoiler alert, this is really simple for a single event rule, but gets a lot more fun for multi-event rules!)

Let’s take a look at an example to see how this works. In this example, we want to detect adversaries who are searching the Windows Registry for credentials that may be stored there. This rule is based on the MITRE ATT&CK technique, Unsecured Credentials: Credentials in Registry. This rule was originally written by the team at SOC Prime and was converted from Sigma. I adapted it to reflect the current technique and sub-technique. I also adapted the event section for greater precision.

Meta

In the meta section, we have a number of fields defined, including the author of the rule, a description of what the rule does, and the severity of the rule. We added a 'last_updated' field as well, as well as additional specificity around the ATT&CK tactic and technique that we are attempting to detect.

This metadata can be seen when viewing the rule detections.


This view provides that summary information at the top of the page and the detections that fired.

Events

The event section contains the criteria that needs to be observed within the logs for the detection to fire. Each item in the event section that is being evaluated will be prepended by a variable. In our example, you can see the string '$selection1' is prepended to our UDM fields. This event variable is arbitrary, but establishing a common taxonomy for your organization is important as you build out your rules. In our documentation, we recommend that '$u' be used for UDM event fields and '$e' used for entity fields.

Wait, what’s an entity field? Don’t worry, we will get to entity fields in a future post.

As we start introducing multiple events into our rules, having that common taxonomy will become important.

Three operators are available to connect criteria together. They are and, or, and not. By default, and is assumed in the absence of other operators. In fact, in the example above, with one piece of criteria on each line, YARA-L reads this as:

$selection1.metadata.event_type = "PROCESS_LAUNCH" and $selection1.target.process.file.full_path = /reg.exe/

Parenthesis can also be used to group items together. The final two lines in our example contain two different registry queries, and the existence of either one will trigger our rule to fire. We can bind them with parenthesis and separate them with the operator or.

($selection1.target.process.command_line = /reg.*query HKLM \/f password \/t REG_SZ \/s/ nocase or

$selection1.target.process.command_line = /reg.*query HKCU \/f password \/t REG_SZ \/s/ nocase)

The 'not operator' provides a way to exclude certain criteria from consideration. If we wanted to exclude a specific user or specific host from consideration, the not operator could be prepended to the event criteria.

Search criteria can take the form of a string match as we see in the first line.

$selection1.metadata.event_type = "PROCESS_LAUNCH"

Regular expression matching is also possible. Chronicle uses RE2 for those who are aficionados of regular expressions. Sadly, I’m not, but I digress. There are functions for regular expressions that will be discussed in a future blog but we can use forward slashes around a value to denote a regular expression. We can add '.*' to handle variability in spaces, file extensions, or other unpredictability within the values that we are searching in our criteria. Because the forward slash is used to bound our search term and denote a regular expression, backslashes are used as escape characters to indicate that forward slashes within the string are to be treated as a forward slash and not as the end of a regular expression.

$selection1.target.process.command_line = /reg.*query HKLM \/f password \/t REG_SZ \/s/

If we wanted to loosen our search terms to find greater variability in our events, we could add additional .* between our values. We can also add the modifier nocase to the end of our expression to insulate ourselves against adversaries mixing their case in their commands.

($selection1.target.process.command_line = /reg.*query HKLM \/f password \/t REG_SZ \/s/ nocase or

$selection1.target.process.command_line = /reg.*query HKCU \/f password \/t REG_SZ \/s/ nocase)

Condition

The final mandatory section, and the last one we will talk about today, is the condition section. Now, for a single event rule, the condition section is kind of boring. It is basically going to be $selection1 or whatever the variable we are using for the event itself.

When we get to multi-event rules, this will get more interesting.

With that, we have a single event rule. But before deploying it, perhaps we want to test it against our events to ensure we are getting detections that we expect. Chronicle has us covered with the test rule capability within the rule editor.

Simply specify the time range and click 'Run Test' and the rule will run against our data during the time period specified and return any detections.

Here you can see that both Windows/4688 and Sysmon/1 events are triggered as their own detections because both are PROCESS_LAUNCH event types. In future posts, we will show how to consolidate them into a single detection! We can also drill into both the raw and UDM event to see the underlying data and can further refine our rule as needed.

I hope this provides you a good understanding around how a rule is created. While this was a relatively simple example, building a good foundation is important, and the concepts covered here will make it easier as we move into more robust rule development.

Until next time!

Let’s work together
Ready for Google-speed threat detection and response?
Contact us