YARA-L 2.0 语言概览
YARA-L 2.0 是一种计算机语言,用于创建在企业日志数据注入您的 Google Security Operations 实例时搜索数据的规则。YARA-L 语法派生自 VirusTotal 开发的 YARA 语言。该语言与 Google Security Operations Detection Engine 配合使用,让您可以在大量数据中寻找威胁和其他事件。
详情请参阅以下内容:
YARA-L 2.0 示例规则
以下示例展示了使用 YARA-L 2.0 编写的规则。每个示例都展示了如何关联规则语言中的事件。
规则和调整
以下规则会检查事件数据中是否存在特定模式,如果存在,则创建检测。此规则包含用于跟踪事件类型和 metadata.event_type
UDM 字段的变量 $e1
。该规则会检查与 e1
匹配的正则表达式的特定出现情况。当事件 $e1
发生时,系统会创建检测。规则中包含 not
条件,用于排除某些非恶意路径。您可以添加 not
条件以防止出现假正例。
rule suspicious_unusual_location_svchost_execution
{
meta:
author = "Google Cloud Security"
description = "Windows 'svchost' executed from an unusual location"
yara_version = "YL2.0"
rule_version = "1.0"
events:
$e1.metadata.event_type = "PROCESS_LAUNCH"
re.regex($e1.principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex($e1.principal.process.command_line, `\\Windows\\System32\\`) nocase
condition:
$e1
}
不同城市的登录信息
以下规则会在 5 分钟内搜索从两个或多个城市登录过您的企业的用户:
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 变量:$user
事件变量:$udm
占位符变量:$city
和 $user
下面介绍了此规则的工作原理:
- 对用户名为 (
$user
) 的事件进行分组,并在找到匹配项时返回该值 ($user
)。 - 时间范围为 5 分钟,表示只有间隔不到 5 分钟的事件相关联。
- 搜索事件类型为 USER_LOGIN 的事件组 (
$udm
)。 - 对于该事件组,该规则会将用户 ID 命名为
$user
,并将登录城市命名为$city.
- 如果 5 分钟时间范围内事件组 (
$udm
) 中的不同city
值(表示为#city
)数量大于 1,则返回匹配项。
快速创建和删除用户
以下规则可搜索在 4 小时内创建然后删除的用户:
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
}
事件变量:$create
和 $delete
Match 变量:$user
占位符变量:不适用
下面介绍了此规则的工作原理:
- 对用户名为 (
$user
) 的事件进行分组,并在找到匹配项时返回该值 ($user
)。 - 时间范围为 4 小时,这意味着只有不到 4 小时的事件才会关联。
- 搜索两个事件组(
$create
和$delete
,其中$create
等同于#create >= 1
)。 $create
对应于USER_CREATION
事件,并以$user
形式调用用户 ID。$user
用于将两组事件联接在一起。$delete
对应于USER_DELETION
事件,并以$user
形式调用用户 ID。此规则查找两个事件组中用户标识符相同的匹配项。- 此规则查找事件
$delete
发生的时间晚于$create
事件的情况,并在发现时返回匹配项。
单事件规则
单事件规则是与单个事件相关联的规则。单事件规则可以是:
- 没有匹配部分的任何规则。
- 包含
match
部分和condition
部分的规则仅检查是否存在 1 个事件(例如,“$e”“#e > 0”“#e >= 1”“1 <= #e”“0 < #e”)。
例如,以下规则会搜索用户的登录事件,然后返回在 Google 安全运营账号中存储的企业数据中遇到的首个事件:
rule SingleEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
condition:
$e
}
下面是包含匹配部分的单事件规则的另一个示例。此规则会搜索在 5 分钟内至少登录过一次的用户。它只检查用户登录事件是否存在。
rule SingleEventRule {
meta:
author = "alice@example.com"
description = "windowed single event example rule"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 5m
condition:
#e > 0
}
rule MultiEventRule{
meta:
author = "alice@example.com"
description = "Rule with outcome condition and simple existence condition on one event variable"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 10m
outcome:
$num_events_in_match_window = count($e.metadata.id)
condition:
#e > 0 and $num_events_in_match_window >= 10 // Could be rewritten as #e >= 10
}
多事件规则
使用多事件规则对指定时间范围内的多个事件进行分组,并尝试找到事件之间的相关性。典型的多事件规则包含以下部分:
match
部分,用于指定需要对事件进行分组的时间范围。condition
部分,用于指定应触发检测和检查多个事件是否存在的条件。
例如,以下规则会搜索在 10 分钟内至少登录了 10 次的用户:
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
}
IP 地址范围内的单个事件
以下示例展示了一条规则,用于搜索两个特定用户和特定 IP 地址范围之间的匹配项:
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 和 all 规则示例
以下规则会搜索所有来源 IP 地址在 5 分钟的时间内与已知安全的 IP 地址不匹配的登录事件。
rule SuspiciousIPLogins {
meta:
author = "alice@example.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
}
规则中的正则表达式
以下 YARA-L 2.0 正则表达式示例搜索从 altostrat.com 网域收到电子邮件的事件。由于 nocase
已添加到 $host
变量 regex
比较和 regex
函数,因此这些比较都不区分大小写。
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
}
滑动窗口规则示例
以下 YARA-L 2.0 滑动窗口示例搜索 firewall_1
事件后缺少 firewall_2
事件。after
关键字与数据透视事件变量 $e1
结合使用,指定在关联事件时应仅检查每个 firewall_1
事件 10 分钟后。
rule SlidingWindowRuleExample {
meta:
author = "alice@example.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
}
零值排除示例
规则引擎会隐式滤除 match
部分中使用的所有占位符的零值。如需了解详情,请参阅 match
部分中的零值处理。您可以使用 allow_zero_values
选项停用此功能,如 allow_zero_values 中所述。
但是,对于其他引用的事件字段,除非您明确指定此类条件,否则不会排除零值。
rule ExcludeZeroValues {
meta:
author = "alice@example.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. The rule behaves as if the
// predicate, `$hostname != ""` was added to the events section, because
// `$hostname` is used in the match section.
$hostname over 1h
condition:
$e1 and $e2
}
包含 outcome
部分的规则示例
您可以在 YARA-L 2.0 规则中添加可选的 outcome
部分,以提取每次检测的其他信息。在“条件”部分中,您还可以针对结果变量指定条件。您可以使用检测规则的 outcome
部分设置要供下游使用的数据变量。例如,您可以根据要分析的事件中的数据设置严重程度得分。
详情请参阅以下内容:
包含结果部分的多事件规则:
以下规则会查看两个事件,以获取 $hostname
的值。如果 $hostname
的值在 5 分钟内匹配,则系统会应用严重程度得分。在 match
部分中添加时间段后,规则会在指定时间段内进行检查。
rule OutcomeRuleMultiEvent {
meta:
author = "Google Cloud Security"
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)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}
rule OutcomeRuleMultiEvent {
meta:
author = "alice@example.com"
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:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if(total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}
包含结果部分的单事件规则:
rule OutcomeRuleSingleEvent {
meta:
author = "alice@example.com"
events:
$u.metadata.event_type = "FILE_COPY"
$u.principal.file.size = $file_size
$u.principal.hostname = $hostname
outcome:
$suspicious_host = $hostname
$admin_severity = if($u.principal.userid in %admin_users, "SEVERE", "MODERATE")
$severity_tag = if($file_size > 1024, $admin_severity, "LOW")
condition:
$u
}
将多事件结果规则重构为单事件结果规则。
您可以将 outcome
部分用于单事件规则(不含 match
部分的规则)和多事件规则(含 match
部分的规则)。如果您之前仅为了使用结果部分而将规则设计为多事件规则,则可以选择删除 match
部分来重构这些规则,以提升性能。请注意,由于您的规则不再包含用于应用分组的 match
部分,因此您可能会收到更多检测结果。只有使用一个事件变量的规则才能进行此重构,如以下示例所示。
仅使用一个事件变量的多事件结果规则(非常适合重构):
rule OutcomeMultiEventPreRefactor {
meta:
author = "alice@example.com"
description = "Outcome refactor rule, before the refactor"
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
}
您可以通过删除 match
部分来重构规则。请注意,您还必须移除 outcome
部分中的汇总,因为规则现在将是单个事件。如需详细了解汇总,请参阅结果汇总。
rule OutcomeSingleEventPostRefactor {
meta:
author = "alice@example.com"
description = "Outcome refactor rule, after the refactor"
events:
$u.udm.principal.hostname = $hostname
// We deleted the match section.
outcome:
// We removed the max() aggregate.
$risk_score = if($hostname = "my-hostname", 100, 50)
condition:
$u
}
函数到占位符规则示例
您可以将占位符变量分配给函数调用的结果,并可以在规则的其他部分(例如 match
部分、outcome
部分或 condition
部分)中使用该占位符变量。请参阅以下示例:
rule FunctionToPlaceholderRule {
meta:
author = "alice@example.com"
description = "Rule that uses function to placeholder assignments"
events:
$u.metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture($u.network.email.from , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// uid@??? -> uid@company.com
$email_from_normalized = strings.concat(
re.capture($u.network.email.from , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week($u.metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1, 10, 0) +
if($dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
}
结果条件示例规则
在 condition
部分中,您可以使用 outcome
部分中定义的结果变量。以下示例演示了如何使用结果条件过滤风险得分,以减少检测中的噪声。
rule OutcomeConditionalRule {
meta:
author = "alice@example.com"
description = "Rule that uses outcome conditionals"
events:
$u.metadata.event_type = "FILE_COPY"
$u.principal.file.size = $file_size
$u.principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week($u.metadata.collected_timestamp.seconds)
outcome:
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
condition:
$u and $risk_score >= 10
}