Overview of the YARA-L 2.0 language
YARA-L 2.0 is a computer language used to create rules for searching through your enterprise log data as it is ingested into your Chronicle account. The YARA-L syntax is derived from the YARA language developed by VirusTotal. The language works in conjunction with the Chronicle Detection Engine and enables you to hunt for threats and other events across large volumes of data. See also YARA-L 2.0 language syntax
YARA-L 2.0 example rules
The following examples show rules written in YARA-L 2.0. Each demonstrates how to correlate events within the rule language.
Logins from different cities
The following rule searches for users that have logged in to your enterprise from two or more cities in less than 5 minutes:
rule DifferentCityLogin {
meta:
events:
$udm.metadata.event_type = "USER_LOGIN"
$udm.principal.user.userid = $user
$udm.principal.location.city = $city
match:
$user over 5m
condition:
$udm and #city > 1
}
Match variable: $user
Event variable:$udm
Placeholder variable: $city
and $user
The following describes how this rule works:
- Groups events with username (
$user
) and returns it ($user
) when a match is found. - Timespan is 5 minutes, meaning only events that are less than 5 minutes apart are correlated.
- Searching for an event group (
$udm
) whose event type is USER_LOGIN. - For that event group, the rule calls the user id as
$user
and the login city as$city.
- Returns a match if the distinct number of
$city
values is greater than 1 in the event group ($udm
) within the 5 minute time range.
Rapid user creation and deletion
The following rule searches for users that have been created and then deleted within 4 hours:
rule UserCreationThenDeletion {
meta:
events:
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user over 4h
condition:
$create and $delete
}
Event variables:$create
and $delete
Match variable: $user
Placeholder variable: N/A
The following describes how this rule works:
- Groups events with username (
$user
) and returns it ($user
) when a match is found. - Time window is 4 hours, meaning only events separated by less than 4 hours are correlated.
- Searches for two event groups (
$create
and$delete
, where$create
is equivalent to#create >= 1
). $create
corresponds toUSER_CREATION
events and calls the user id as$user
.$user
is used to join the two groups of events together.$delete
corresponds toUSER_DELETION
events and calls the user id as$user
. This rule looks for a match where the user identifier in the two event groups is the same.- This rule looks for cases where the event from
$delete
happens later than the event from$create
, returning a match when discovered.
Single-event versus multi-event
The following example rules show how you could create a rule to search for a single event and then modify it to search for multiple events.
Here is the single event version of the rule:
rule SingleEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
condition:
$e
}
This rule simply searches for a user login event and would return the first one it encounters within the enterprise data stored within your Chronicle account.
Here is a multi-event version of the rule:
rule MultiEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 10m
condition:
#e >= 10
}
The rule searches for a user who has logged in at least 10 times in less than 10 minutes.
Single event within range of IP addresses
The following example shows a single event rule searching for a match between two specific users and a specific range of IP addresses:
rule OrsAndNetworkRange {
meta:
author = "noone@altostrat.com"
events:
// Checks CIDR ranges.
net.ip_in_range_cidr($e.principal.ip, "203.0.113.0/24")
// Detection when the hostname field matches either value using or.
$e.principal.hostname = /pbateman/ or $e.principal.hostname = /sspade/
condition:
$e
}
any and all rule example
The following rule searches for login events where all source IP addresses do not match an IP address known to be secure within a timespan of 5 minutes.
rule SuspiciousIPLogins {
meta:
author = "noone@google.com"
events:
$e.metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all $e.principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
$e.principal.ip = $ip
match:
$ip over 5m
condition:
$e
}
Regular expressions in a rule
The following YARA-L 2.0 regular expression example searches for events with emails received from the altostrat.com domain. Since nocase
has been added to the $host
variable regex
comparison and the regex
function, both these comparisons are case insensitive.
rule RegexRuleExample {
meta:
author = "noone@altostrat.com"
events:
$e.principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex($e.network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
condition:
#e > 10
}
Sliding window rule example
The following YARA-L 2.0 sliding window example searches for the absence of
firewall_2
events after firewall_1
events. The after
keyword is used with
the pivot event variable $e1
to specify that only 10 minute windows after each
firewall_1
event should be checked when correlating events.
rule SlidingWindowRuleExample {
meta:
author = "noone@google.com"
events:
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
$host over 10m after $e1
condition:
$e1 and !$e2
}
Zero value exclusion example
If the rule does not specify allow_zero_values
options, zero values are not
returned from match variable values. However, for other referenced event fields,
zero values are not excluded unless you explicitly specify such conditions. See
here for more details.
rule ExcludeZeroValues {
meta:
"author" = "noone@google.com"
events:
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
match:
// $hostname cannot be empty string.
$hostname over 1h
condition:
$e1 and $e2
}
Rule with outcome section example
You can add the optional outcome
section in YARA-L 2.0 rule to extract
additional information of each detection. You can find the syntax
of this section and the overview of this section on how to use it.
rule DetectionWithOutcomeSectionAndConditionalsAndAddition {
meta:
events:
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$risk_score =
max(
100
+ if($hostname = "my-hostname", 100, 50)
+ if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
condition:
$u and $asset_context
}