New to Google SecOps: Building a Rule Using Meta Labels

jstoner
Staff

Today’s blog is a continuation of our mini-series on building composite rules. In our last blog, we used descriptors found within a detection to build a composite rule. This time, we will expand our composite detection use case by leveraging labels and values found in the meta section of our producer rules.

When we discussed detection descriptors last time, we introduced the collections endpoint where values like the rule name, rule ID and more are stored. Did you know that when a detection is triggered the labels and the values in the meta section of a rule are stored in this endpoint? Maybe you said yes because why else would this blog be written, but I suspect you may not have been aware of that and that’s ok.

Let’s start with a nice starter query, executed in dashboards and see what information we have in the detections dataset as it pertains to meta labels and values.

This search is returning all detections for the time window in the chart or dashboard. We are aggregating by the rule name and outputting two outcome variables called $meta_label and $meta_values.

$rule_name = detection.detection.rule_name
match:
   $rule_name

outcome:
 $meta_label = array_distinct(detection.detection.rule_labels.key)
 $meta_values = array_distinct(detection.detection.rule_labels.value)

These two fields contain all of the labels and values found in the meta section of a rule. In the results, we can see that the meta_label column contains values like rule_name, author, mitre_attack_technique and the column meta_values contains values like Google Cloud Security, TA0007 and Windows. That’s all well and good but a couple of arrays in this form isn’t really what I had in mind.

ntc-composite-meta-01.png

The good news is that Google Security Operations (SecOps) uses a specific format when presented with key/value pairs like these. Generically, the format is 

UDM_field_name["key"] = "value"

This means that if we wanted to use a key/value pair in the filtering statement or events section of a rule, we could build an expression like this where error_number is the key and some value other than 0 is the value of interest.

$block.additional.fields["error_number"] != "0"

It also means that when we don’t want to filter on a key/value pair and just want all of the values for a specific key, we can build an expression in the outcome section of a search or rule like this, where the rule_labels with the key of tactic will output to the outcome variable $mitre_tactic the value for that detection.

  $mitre_tactic = detection.detection.rule_labels["tactic"]

With that brief interlude into key/value pairs, let’s return to the task at hand. Returning to our query, we could dip into one of the detection descriptors from last time, alert_state, and add this to the query. We can also use other YARA-L functions like strings.starts_with to narrow the detections to just detections that originate from custom rules, that is rule IDs that start with ru. Fun fact, rule IDs that are associated with curated detections start with ur. 

$ruleName = detection.detection.rule_name
detection.detection.alert_state = "NOT_ALERTING"
strings.starts_with(detection.detection.rule_id, "ru")

match:
   $ruleName

outcome:
 $severity = array_distinct(detection.detection.rule_labels["severity"])
 $mitre_tactic = array_distinct(detection.detection.rule_labels["tactic"])
 $mitre_technique = array_distinct(detection.detection.rule_labels["technique"])
 $description = array_distinct(detection.detection.rule_labels["description"])

In the outcome section, we have key/value pairs representing the meta section labels severity, tactic, technique and description. Because we are grouping the query by rule name, we need to apply an aggregation function to each of the fields in the outcome section and to prevent duplicate values, we are using array_distinct

ntc-composite-meta-02.png

In the results, we can see our rule name and the values associated with each of our meta section labels. For instance, the first rule has a severity of Low, a tactic of TA0007, a technique of T1069.002 and a description that is too long for me to type, but you get the idea.

With that background, let’s use meta labels and values to build a composite rule. Remember that we have a series of rules already written that are generating detections and these are what the composite rule will draw from. For good measure, we are going to build on some of the concepts from last time and use descriptors that the system generates around the detection dataset as well in our composite rule. 

ntc-composite-meta-03.png

The composite rule will return detections where the meta section has a label of tactic and a value of TA0007, short for Discovery in MITRE ATT&CK, with a common hostname. Further, we are going to only use detections that have not alerted and have a rule type of single event.

Let's look at our rule. In the events section, we have the detection descriptors for the rule type and alert state and their associated enumerated values. The next line of criteria is for the key/value pair for the meta label tactic and the value of TA0007. 

The match variable $hostname, is based on a common value in our underlying detections match variable named $hostname. The idea is that the underlying rules that created the initial set of detections aggregated (matched) on a variable named hostname and we are just re-using that value and the aggregation window for all detections must occur within two hours. 

 

rule composite_mitre_attack_discovery_tactic_by_hostname {

meta:
   author = "Google Cloud Security"
   description = "Detects multiple producer rules with a ATT&CK tactic of discovery grouped by hostname"
   severity = "High"
   priority = "High"
   type = "composite"

events:
  $detect_prod.detection.detection.alert_state = "NOT_ALERTING"
  $detect_prod.detection.detection.rule_type = "SINGLE_EVENT"  
  $detect_prod.detection.detection.rule_labels["tactic"] = "TA0007"

  $detect_prod.detection.detection.detection_fields["hostname"] = $hostname

 match:
  $hostname over 2h

outcome:
  $risk_score = 60
  $mitre_tactic = array_distinct($detect_prod.detection.detection.rule_labels["tactic"])
  $mitre_technique = array_distinct($detect_prod.detection.detection.rule_labels["technique"])
  $total_detection_count = count($detect_prod.detection.detection.rule_id)

condition:
  $detect_prod and $total_detection_count > 3
}

The outcome section is writing the MITRE ATT&CK tactic, associated techniques and a detection count to variables for display or for use in the condition section of the rule. When building composite rules, in most cases, I don’t want to go through this effort and then detect on a single detection, so I’ll use $total_detection_count and add a threshold to the condition section that the composite rule won’t trigger unless there are more than three detections within the two hour window for the same hostname that meet the event criteria.

ntc-composite-meta-04.png

When we test our composite rule, we find that we have six detections that meet the composite rule criteria. One of them has a hostname of win-adfs. Using the column manager, we can add outcome variables from the composite rule for MITRE ATT&CK tactic and technique to the view. As you can see, we can expand the composite detection to view the underlying detections and then down another level to the underlying events for those detections.

In this blog, we used meta section labels and their associated values to build a composite rule. Not only that, we leveraged detection descriptors like the alert state and the rule type to narrow the pool of detections that could be leveraged in the composite detection to more finely tune the detections available for use. This specific application of composite rules using meta labels and values assumes that your underlying rules have these descriptors in place, so if you don’t, you may want to consider doing that first!

The use of key/value pairs in the meta section is a powerful method to focus specific use cases like this one where we are able to use recognized industry frameworks like MITRE ATT&CK to logically group detections. We will continue using key/value pairs in the next blog as we look at outcome variables and how they can be used in composite rules!