YARA-L 2.0 语言语法
本部分介绍 YARA-L 语法的主要元素。另请参阅 YARA-L 2.0 语言概览。
规则结构
对于 YARA-L 2.0,您必须按以下顺序指定变量声明、定义和用法:
- meta
- events
- match(可选)
- outcome(可选)
- condition
- options(可选)
下面说明了规则的通用结构:
rule <rule Name>
{
meta:
// Stores arbitrary key-value pairs of rule details, such as who wrote
// it, what it detects on, version control, etc.
events:
// Conditions to filter events and the relationship between events.
match:
// Values to return when matches are found.
outcome:
// Additional information extracted from each detection.
condition:
// Condition to check events and the variables used to find matches.
options:
// Options to turn on or off while executing this rule.
}
元部分语法
元部分由多个行组成,其中每个行定义一个键值对。键部分必须是不带英文引号的字符串,而值部分必须是带英文引号的字符串:
<key> = "<value>"
以下是有效的 meta
部分行的示例:
meta:
author = "Google"
severity = "HIGH"
“事件”部分语法
在 events
部分中,列出谓词以指定以下内容:
- 变量声明
- 事件变量过滤条件
- 事件变量联接
变量声明
对于变量声明,请使用以下语法:
<EVENT_FIELD> = <VAR>
<VAR> = <EVENT_FIELD>
这两个示例是等效的,如以下示例所示:
$e.source.hostname = $hostname
$userid = $e.principal.user.userid
此声明表明此变量表示事件变量的指定字段。当事件字段是重复字段时,匹配变量可以表示数组中的任何值。也可以将多个事件字段分配给单个匹配或占位符变量。这是一个传递性联接条件。
例如,以下方法:
$e1.source.ip = $ip
$e2.target.ip = $ip
等效于:
$e1.source.ip = $ip
$e1.source.ip = $e2.target.ip
使用变量时,必须通过变量声明来声明该变量。如果使用变量时未做任何声明,则会被视为编译错误。
事件变量过滤条件
对单个事件变量执行操作的布尔表达式被视为过滤条件。
事件变量联接
规则中使用的所有事件变量必须采用以下任一方式与所有其他事件变量联接:
通过两个联接事件变量的事件字段之间的相等比较直接联接,例如:
$e1.field = $e2.field
。表达式不得包含算术运算。通过仅涉及一个事件字段的传递联接间接联接(请参阅变量声明中的“传递联接”定义)。表达式不得包含算术运算。
例如,假设规则中使用了 $e1、$e2 和 $e3,以下 events
部分有效。
events:
$e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2
$e2.principal.ip = $e3.src.ip // $e2 joins with $e3
events:
// $e1 joins with $e2 via function to event comparison
re.capture($e1.src.hostname, ".*") = $e2.target.hostname
events:
// $e1 joins with $e2 via an `or` expression
$e1.principal.hostname = $e2.src.hostname
or $e1.principal.hostname = $e2.target.hostname
or $e1.principal.hostname = $e2.principal.hostname
events:
// all of $e1, $e2 and $e3 are transitively joined via the placeholder variable $ip
$e1.src.ip = $ip
$e2.target.ip = $ip
$e3.about.ip = $ip
events:
// $e1 and $e2 are transitively joined via function to event comparison
re.capture($e2.principal.application, ".*") = $app
$e1.principal.hostname = $app
但是,以下是示例 events
部分无效。
events:
// Event to arithmetic comparison is an invalid join condition for $e1 and $e2.
$e1.principal.port = $e2.src.port + 1
events:
$e1.src.ip = $ip
$e2.target.ip = $ip
$e3.about.ip = "192.1.2.0" //$e3 is not joined with $e1 or $e2.
events:
$e1.src.port = $port
// Arithmetic to placeholder comparison is an invalid transitive join condition.
$e2.principal.port + 800 = $port
匹配部分语法
在 match
部分中,列出群组事件的匹配变量,然后再检查匹配条件。这些字段随每个匹配项返回。
- 指定每个匹配变量在
events
部分中表示的内容。 - 指定用于在
over
关键字之后关联事件的时长。时间时长之外的事件会被忽略。 使用以下语法指定时长:
<number><m/h/d>
其中
m/h/d
分别表示分钟、小时和天。您可以指定的最短时间为 1 分钟。
可指定的最长时间为 48 小时。
以下是有效 match
的示例:
$var1, $var2 over 5m
当规则找到匹配项时,此语句返回 $var1
和 $var2
(在 events
部分中定义)。指定时间为 5 分钟。相互间隔超过 5 分钟的事件是不相关的,因此规则会忽略这些事件。
下面是有效 match
部分的另一个示例:
$user over 1h
当规则找到匹配项时,此语句会返回 $user
。指定的时间窗口为 1 小时。相互间隔超过一小时的活动之间没有关联。该规则不会将其视为检测。
下面是有效 match
部分的另一个示例:
$source_ip, $target_ip, $hostname over 2m
当规则找到匹配项时,此语句会返回 $source_ip
、$target_ip
和 $hostname
。指定的时间窗口为 2 分钟。间隔超过 2 分钟的事件不相关。该规则不会将其视为检测。
以下示例说明了无效的 match
部分:
var1, var2 over 5m // invalid variable name
$user 1h // missing keyword
匹配部分中的零值处理
规则引擎会隐式滤除匹配部分中使用的所有占位符的零值(""
表示字符串,0
表示数字,false
表示布尔值,位置 0 中的值表示枚举类型)。以下示例展示了用于滤除零值的规则。
rule ZeroValuePlaceholderExample {
meta:
events:
// Because $host is used in the match section, the rule behaves
// as if the following predicate was added to the events section:
// $host != ""
$host = $e.principal.hostname
// Because $otherPlaceholder was not used in the match section,
// there is no implicit filtering of zero values for $otherPlaceholder.
$otherPlaceholder = $e.principal.ip
match:
$host over 5m
condition:
$e
}
不过,如果将占位符分配给函数,规则不会隐式滤除匹配部分中使用的占位符的零值。以下示例展示了用于滤除零值的规则:
rule ZeroValueFunctionPlaceholder {
meta:
events:
// Even though $ph is used in the match section, there is no
// implicit filtering of zero values for $ph, because $ph is assigned to a function.
$ph = re.capture($e.principal.hostname, "some-regex")
match:
$ph over 5m
condition:
$e
}
如需停用对零值的隐式过滤,您可以在“Options”部分中使用 allow_zero_values
选项。
跳跃窗口
默认情况下,包含匹配部分的 YARA-L 2.0 规则使用跃点窗口进行评估。规则的执行时间范围分为一组重叠的跃点窗口,每个窗口的持续时间都在 match
部分指定。然后,在每个跃点窗口内关联事件。
例如,对于在时间范围 [1:00, 2:00] 内运行且 match
部分超过 30m
的规则,可能生成的一组重叠跳转时间窗口为 [1:00, 1:30]、[1:03, 1:33] 和 [1:06, 1:36]。这些时间范围用于关联多个事件。
滑动窗口
使用跃点窗口搜索按特定顺序发生的事件(例如,e1
可在 e2
后最多 2 分钟内发生)并不有效。只有当事件 e1
与事件 e2
发生在同一跃点窗口内时,系统才会将它们相关联。
若要更高效地搜索此类事件序列,可以使用滑动窗口。以指定的数据透视事件变量开始或结束时,会生成时长为 match
区段的滑动窗口。然后,在每个滑动窗口内,事件是相关的。这样,您就可以搜索按特定顺序发生的事件(例如,e1
会在 e2
的 2 分钟内发生)。如果事件 e1
发生在事件 e2
后的滑动窗口内,则事件 e1
与事件 e2
的发生是相关的。
在规则的 match
部分中指定滑动窗口,如下所示:
<match-var-1>, <match-var-2>, ... over <duration> before|after <pivot-event-var>
数据透视事件变量是滑动窗口所基于的事件变量。如果使用 before
关键字,则系统会生成滑动窗口,以每次执行数据透视事件结尾。如果使用了 after
关键字,则系统会从每次发生透视事件开始生成滑动窗口。
以下是有效滑动窗口用法的示例:
$var1, $var2 over 5m after $e1
$user over 1h before $e2
请参阅滑动窗口规则示例。
Google 建议不要对单事件规则使用滑动窗口,因为滑动窗口旨在检测多个事件。如果您的某条规则属于此类别,Google 建议您采用以下某种权宜解决方法:
- 将规则转换为使用多个事件变量,如果规则要求事件发生多次,请更新条件部分。
- 您可以考虑添加时间戳过滤条件,而不是使用滑动窗口。例如
$permission_change.metadata.event_timestamp.seconds < $file_creation.metadata.event_timestamp.seconds
。
- 您可以考虑添加时间戳过滤条件,而不是使用滑动窗口。例如
- 移除滑动窗口。
结果部分语法
在 outcome
部分中,您最多可以定义 20 个结果变量,并使用任意名称。这些结果将存储在规则生成的检测中。每项检测可能具有不同的结果值。
结果名称 $risk_score
是特殊名称。您可以选择性地定义使用此名称的结果;如果定义该结果,则必须是整数或浮点类型。如果填充了该名称,risk_score
将显示在来自规则检测的提醒的“企业数据洞察”视图中。
如果您未在规则的结果部分中添加 $risk_score
变量,系统会设置以下默认值之一:
- 如果规则配置为生成提醒,则
$risk_score
设置为 40。 - 如果未将规则配置为生成提醒,则
$risk_score
会设置为 15。
$risk_score
的值存储在 security_result.risk_score
UDM 字段中。
结果变量数据类型
每个结果变量可以具有不同的数据类型,该数据类型由用于计算结果变量的表达式决定。我们支持以下结果数据类型:
- 整数
- 浮点数
- 字符串
- 整数列表
- 浮点数列表
- 字符串列表
条件逻辑
您可以使用条件逻辑来计算结果的值。条件使用以下语法模式指定:
if(BOOL_CLAUSE, THEN_CLAUSE)
if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)
您可以将条件表达式理解为“如果 BOOL_CLAUSE 为 true,则返回 THEN_CLAUSE,否则返回 ELSE_CLAUSE”。
BOOL_CLAUSE 的求值结果必须为布尔值。BOOL_CLAUSE 表达式采用的格式与 events
部分中的表达式类似。例如,该表达式可以包含以下内容:
具有比较运算符的 UDM 字段名称,例如:
if($context.graph.entity.user.title = "Vendor", 100, 0)
events
部分中定义的占位符变量,例如:if($severity = "HIGH", 100, 0)
outcome
部分中定义的另一个结果变量,例如:if($risk_score > 20, "HIGH", "LOW")
返回布尔值的函数,例如:
if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)
在参考列表中查找,例如:
if($u.principal.hostname in %my_reference_list_name, 100, 0)
汇总比较,例如:
if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)
TheNN_CLAUSE 和 ELSE_CLAUSE 必须是相同的数据类型。我们支持整数、浮点数和字符串。
如果数据类型为整数或浮点数,则可以省略 ELSE_CLAUSE。如果省略,则 ELSE_CLAUSE 计算结果为 0。例如:
`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`
如果数据类型为字符串,或者 THEN_CLAUSE 是占位符变量或结果变量,则必须提供 ELSE_CLAUSE。
数学运算
您可以在规则的 outcome
和 events
部分使用数学运算来计算整数或浮点数据类型。Google 安全操作支持在计算中将加法、减法、乘法、除法和模运算符用作顶级运算符。
以下代码段是 outcome
部分中的计算示例:
outcome:
$risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))
允许对以下类型的运算数执行数学运算,前提是每个运算数和整个算术表达式都经过了适当的汇总(请参阅汇总):
- 数字事件字段
events
部分中定义的数字占位符变量- 在
outcome
部分中定义的数值结果变量 - 返回整数或浮点数的函数
- 返回 int 或浮点值的汇总
不允许对浮点数使用模运算。
结果中的占位符变量
计算结果变量时,您可以使用在规则的事件部分中定义的占位符变量。在此示例中,假设在规则的事件部分定义了 $email_sent_bytes
:
单事件示例:
// No match section, so this is a single-event rule.
outcome:
// Use placeholder directly as an outcome value.
$my_outcome = $email_sent_bytes
// Use placeholder in a conditional.
$other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")
condition:
$e
多事件示例:
match:
// This is a multi event rule with a match section.
$hostname over 5m
outcome:
// Use placeholder directly in an aggregation function.
$max_email_size = max($email_sent_bytes)
// Use placeholder in a mathematical computation.
$total_bytes_exfiltrated = sum(
1024
+ $email_sent_bytes
+ $file_event.principal.file.size
)
condition:
$email_event and $file_event
结果赋值表达式中的结果变量
结果变量可用于派生其他结果变量,类似于 events
部分中定义的占位符变量。您可以在另一个结果变量的赋值中引用结果变量,方法是使用 $
令牌后跟变量名称。必须先定义结果变量,然后才能在规则文本中引用它们。在赋值表达式中使用时,结果变量不得进行汇总(请参阅汇总)。
在以下示例中,结果变量 $risk_score
从结果变量 $event_count
派生其值:
多事件示例:
match:
// This is a multi event rule with a match section.
$hostname over 5m
outcome:
// Aggregates all timestamp on login events in the 5 minute match window.
$event_count = count($login.metadata.event_timestamp.seconds)
// $event_count cannot be aggregated again.
$risk_score = if($event_count > 5, "SEVERE", "MODERATE")
// This is the equivalent of the 2 outcomes above combined.
$risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE")
condition:
$e
结果变量可在结果赋值的右侧的任何类型的表达式中使用,但以下表达式除外:
- 聚合
Arrays.length()
函数调用- 使用
any
或all
修饰符
聚合
重复事件字段是标量值。也就是说,单个变量指向多个值。例如,事件字段变量 $e.target.ip
是一个重复字段,可以包含零个、一个或多个 IP 值。它是一个非标量值。而事件字段变量 $e.principal.hostname
不是重复字段,只有 1 个值(即标量值)。
同样,具有匹配时间范围的规则的结果部分中使用的非重复事件字段和重复事件字段都是非标量值。例如,以下规则使用匹配部分对事件进行分组,并在结果部分中引用非重复事件字段:
rule OutcomeAndMatchWindow{
...
match:
$userid over 5m
outcome:
$hostnames = array($e.principal.hostname)
...
}
规则在执行期间的任何 5 分钟时间段都可能包含 0 个、1 个或多个事件。结果部分会对匹配时间段内的所有事件进行操作。在“结果”部分中提及的任何事件字段变量都可以指向匹配时间范围内每个事件的该字段的零个、一个或多个值。在上面的规则中,如果 5 分钟的时间范围内包含 5 个 $e
事件,则“结果”部分中的 $e.principal.hostname
会指向 5 个不同的主机名。因此,事件字段变量 $e.principal.hostname
是此规则的“结果”部分中的非标量值。
由于结果变量始终必须产生单个标量值,因此任何依赖于结果分配的非标量值都必须进行汇总,以产生单个标量值。在结果部分中,以下是非标量值,必须进行汇总:
- 当规则使用匹配部分时,事件字段(重复或非重复)
- 当规则使用匹配部分时,事件占位符(重复或非重复)
- 当规则不使用匹配部分时,重复的事件字段
- 当规则不使用匹配部分时,重复的事件占位符
在不使用匹配部分的规则中,标量事件字段、标量事件占位符和常量可以封装在汇总中。不过,大多数汇总都会产生封装值,因此没有必要进行此操作。唯一的例外是 array()
汇总,它可用于将标量值转换为数组。
结果变量会被视为汇总:在其他结果分配中引用它们时,不得重新汇总。
您可以使用以下聚合函数:
max()
:输出所有可能值的最大值。仅适用于整数和浮点数。min()
:输出所有可能值的最小值。仅适用于整数和浮点数。sum()
:输出所有可能值的总和。仅适用于整数和浮点数。count_distinct()
:收集所有可能的值,然后输出不同数量的可能的值。count()
:行为类似于count_distinct()
,但会返回相同数量的可能的值。array_distinct()
:收集所有可能的不同值,然后输出这些值的列表。它会将不重复值列表截断为 25 个随机元素。系统会先应用去重操作以获取不重复的列表,然后再应用截断操作。array()
:其行为类似于array_distinct()
,但会返回相同的值列表。它也会将值列表截断为 25 个随机元素。period_start_for_max()
:列出值达到最大值的时间段的开始时间。period_start_for_min()
:列出值的最小值出现的时间段的开始时间。
当规则包含指定必须存在多个事件的 condition
部分时,聚合函数很重要,因为聚合函数会对生成检测的所有事件进行运算。
例如,如果 outcome
和 condition
部分包含以下内容:
outcome:
$asset_id_count = count($event.principal.asset_id)
$asset_id_distinct_count = count_distinct($event.principal.asset_id)
$asset_id_list = array($event.principal.asset_id)
$asset_id_distinct_list = array_distinct($event.principal.asset_id)
condition:
#event > 1
由于条件部分要求每项检测存在多个 event
,因此聚合函数将对多个事件进行运算。假设以下事件生成了一项检测:
event:
// UDM event 1
asset_id="asset-a"
event:
// UDM event 2
asset_id="asset-b"
event:
// UDM event 3
asset_id="asset-b"
则结果的值将是:
- $asset_id_count =
3
- $asset_id_distinct_count =
2
- $asset_id_list =
["asset-a", "asset-b", "asset-b"]
- $asset_id_distinct_list =
["asset-a", "asset-b"]
使用结果部分时的注意事项:
其他说明和限制:
outcome
部分不能引用尚未在events
部分或outcome
部分中定义的新占位符变量。outcome
部分不能使用尚未在events
部分中定义的事件变量。outcome
部分可以使用未在events
部分中使用的事件字段,前提是事件字段所属的事件变量已在events
部分中定义。outcome
部分只能关联已在events
部分中关联的事件变量。当来自不同事件变量的两个事件字段被等式化时,就会出现相关性。
您可以使用 YARA-L 2.0 概览中的结果部分找到示例。 如需详细了解如何通过结果部分对检测进行重复数据删除,请参阅创建情境感知分析。
条件部分语法
- 指定
events
部分中定义的事件和占位符的匹配条件。如需了解详情,请参阅下一部分:事件和占位符条件。 - (可选)使用
and
关键字使用outcome
部分中定义的结果变量指定匹配条件。如需了解详情,请参阅下一部分:结果条件。
统计字符数
#
字符是 condition
部分中的特殊字符。如果在任何事件或占位符变量名称之前使用,它表示满足所有 events
部分条件的不同事件或值的数量。
例如,#c > 1
表示变量 c
必须出现多次。
值字符
$
字符是 condition
部分中的特殊字符。如果在任何结果变量名称之前使用,它表示该结果的值。
如果在任何事件或占位符变量名称(例如 $event
)之前使用,它表示 #event > 0
。
事件和占位符条件
此处列出事件和占位符变量的条件谓词,并与关键字 and
或 or
联接。关键字 and
可用于任何条件之间,但关键字 or
只能在规则只有一个事件变量时使用。
在同一事件的两个占位符之间使用 or
的有效示例:
rule ValidConditionOr {
meta:
events:
$e.metadata.event_type = "NETWORK_CONNECTION"
// Note that all placeholders use the same event variable.
$ph = $e.principal.user.userid // Define a placeholder variable to put in match section.
$ph2 = $e.principal.ip // Define a second placeholder variable to put in condition section.
$ph3 = $e.principal.hostname // Define a third placeholder variable to put in condition section.
match:
$ph over 5m
condition:
$ph2 or $ph3
}
在不同事件的两个条件之间使用 or
的无效示例:
rule InvalidConditionOr {
meta:
events:
$e.metadata.event_type = "NETWORK_CONNECTION"
$e2.graph.metadata.entity_type = "FILE"
$e2.graph.entity.hostname = $e.principal.hostname
$ph = $e.principal.user.userid // Define a placeholder variable to put in match section.
match:
$ph over 5m
condition:
$e or $e2 // This line will cause an error because there is an or between events.
}
有界限和无界限条件
以下条件即为边界条件。它们强制关联事件变量的存在,这意味着任何检测都必须显示相应事件的发生实例。
$var // equivalent to #var > 0
#var > n // where n >= 0
#var >= m // where m > 0
以下条件即为无界限条件。它们允许关联的事件变量不存在,这意味着检测中可能不会出现该事件,并且对事件变量字段的任何引用都会产生零值。无界条件可用于检测一段时间内是否没有发生事件。例如,在 10 分钟内没有缓解措施事件的威胁事件。使用无界条件的规则称为“不存在”规则。
!$var // equivalent to #var = 0
#var >= 0
#var < n // where n > 0
#var <= m // where m >= 0
不存在性要求
非存在性规则必须满足以下要求才能编译:
- 至少一个 UDM 事件必须具有边界条件(即必须至少存在一个 UDM 事件)。
- 如果占位符具有无界条件,则必须与至少一个有界 UDM 事件相关联。
- 如果实体具有无界条件,则必须与至少一个有界 UDM 事件相关联。
请考虑以下省略了条件部分的规则:
rule NonexistenceExample {
meta:
events:
$u1.metadata.event_type = "NETWORK_CONNECTION" // $u1 is a UDM event.
$u2.metadata.event_type = "NETWORK_CONNECTION" // $u2 is a UDM event.
$e1.graph.metadata.entity_type = "FILE" // $e1 is an Entity.
$e2.graph.metadata.entity_type = "FILE" // $e2 is an Entity.
$user = $u1.principal.user.userid // Match variable is required for Multi-Event Rule.
// Placeholder Associations:
// u1 u2
// | \ /
// port ip
// | \
// e1 e2
$u1.target.port = $port
$e1.graph.entity.port = $port
$u1.principal.ip = $ip
$u2.target.ip = $ip
$e2.graph.entity.ip = $ip
// UDM-Entity Associations:
// u1 - u2
// | \ |
// e1 e2
$u1.metadata.event_type = $u2.metadata.event_type
$e1.graph.entity.hostname = $u1.principal.hostname
$e2.graph.entity.hostname = $u1.target.hostname
$e2.graph.entity.hostname = $u2.principal.hostname
match:
$user over 5m
condition:
<condition_section>
}
以下是 <condition_section>
的有效示例:
$u1 and !$u2 and $e1 and $e2
- 所有 UDM 事件和实体都显示在条件部分。
- 至少有一个 UDM 事件是边界事件。
$u1 and !$u2 and $e1 and !$e2
$e2
是无界变量,这是允许的,因为它与有界变量$u1
相关联。如果$e2
未与$u1
相关联,则此值无效。
#port > 50 and #ip = 0
- 条件部分不包含任何 UDM 事件和实体;不过,其中的占位符涵盖了所有 UDM 事件和实体。
$ip
同时分配给$u1
和$u2
,并且#ip = 0
是一个无边界条件。不过,边界条件比无边界条件更强。由于$port
已分配给$u1
,并且#port > 50
是一个边界条件,因此$u1
仍然是边界条件。
以下是 <condition_section>
的无效示例:
$u1 and $e1
- 事件部分中显示的每个 UDM 事件和实体都必须显示在条件部分中(或为其分配一个显示在条件部分中的占位符)。
$u1, $u2, $e1, $u2, #port > 50
- 不允许使用英文逗号作为条件分隔符。
!$u1 and !$u2 and $e1 and $e2
- 违反了至少有一个 UDM 事件有边界的第一个要求。
($u1 or #port < 50) and $u2 and $e1 and $e2
- 不支持将
or
关键字与无界条件搭配使用。
- 不支持将
($u1 or $u2) and $e1 and $e2
- 不支持在不同事件变量之间使用
or
关键字。
- 不支持在不同事件变量之间使用
not $u1 and $u2 and $e1 and $e2
- 不允许在事件和占位符条件中使用
not
关键字。
- 不允许在事件和占位符条件中使用
#port < 50 and #ip = 0
- 现有的占位符涵盖了所有 UDM 事件和实体;但是,所有条件都是无边界的。这意味着,所有 UDM 事件都没有边界,导致规则无法编译。
结果条件
此处列出结果变量的条件谓词,这些谓词与关键字 and
或 or
联接,或以关键字 not
开头。
请根据结果变量的类型以不同的方式指定结果条件:
整数:使用运算符
=, >, >=, <, <=, !=
与整数字面量进行比较,例如:$risk_score > 10
浮点数:使用运算符
=, >, >=, <, <=, !=
与浮点字面量进行比较,例如:$risk_score <= 5.5
string:使用
=
或!=
与字符串字面量进行比较,例如:$severity = "HIGH"
整数或数组列表:使用
arrays.contains
函数指定条件,例如:arrays.contains($event_ids, "id_1234")
规则分类
在包含匹配部分的规则中指定结果条件意味着该规则将被归类为多事件规则,从而计入规则配额。如需详细了解单事件和多事件分类,请参阅单事件规则和多事件规则。
选项部分语法
在 options
部分中,您可以指定规则的选项。以下示例展示了如何指定选项部分:
rule RuleOptionsExample {
// Other rule sections
options:
allow_zero_values = true
}
您可以使用语法 key = value
指定选项,其中 key
必须是预定义的选项名称,value
必须是选项的有效值,如下方选项所示:
allow_zero_values
此选项的有效值为 true
和 false
,用于确定此选项是否启用。默认值为 false
。如果规则中未指定此选项,则系统会停用此选项。
如需启用此设置,请将以下内容添加到规则的“选项”部分:allow_zero_values = true
。这样做可以防止规则隐式滤除匹配部分中使用的占位符的零值,如匹配部分中的零值处理中所述。
布尔表达式
布尔表达式是具有布尔类型的表达式。
比较
对于用作条件的二进制表达式,请使用以下语法:
<EXPR> <OP> <EXPR>
表达式可以是事件字段、变量、字面量或函数表达式。
例如:
$e.source.hostname = "host1234"
$e.source.port < 1024
1024 < $e.source.port
$e1.source.hostname != $e2.target.hostname
$e1.metadata.collected_timestamp.seconds > $e2.metadata.collected_timestamp.seconds
$port >= 25
$host = $e2.target.hostname
"google-test" = strings.concat($e.principal.hostname, "-test")
"email@google.org" = re.replace($e.network.email.from, "com", "org")
如果双方均为字面量,则将其视为编译错误。
Functions
某些函数表达式会返回布尔值,可用作 events
部分中的单个谓词。此类函数包括:
re.regex()
net.ip_in_range_cidr()
例如:
re.regex($e.principal.hostname, `.*\.google\.com`)
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")
引用列表表达式
您可以在“事件”部分使用参考列表。如需了解详情,请参阅参考列表部分。
逻辑表达式
您可以在 events
部分中使用逻辑 and
和逻辑 or
运算符,如以下示例所示:
$e.metadata.event_type = "NETWORK_DNS" or $e.metadata.event_type = "NETWORK_DHCP"
($e.metadata.event_type = "NETWORK_DNS" and $e.principal.ip = "192.0.2.12") or ($e.metadata.event_type = "NETWORK_DHCP" and $e.principal.mac = "AB:CD:01:10:EF:22")
not $e.metadata.event_type = "NETWORK_DNS"
默认情况下,优先级从高到低的顺序是 not
、and
、or
。
例如,如果在表达式中明确定义了运算符 or
和 and
,则“a or b and c”的计算结果为“a or (b and c)”。
在 events
部分中,如果未显式定义运算符,则使用 and
运算符联接谓词。
如果表达式中隐含 and
运算符,则求值顺序可能会有所不同。
例如,请考虑以下比较表达式,其中 or
已明确定义。隐含使用 and
运算符。
$e1.field = "bat"
or $e1.field = "baz"
$e2.field = "bar"
此示例的解读如下:
($e1.field = "bat" or $e1.field = "baz")
and ($e2.field = "bar")
由于 or
是显式定义的,因此系统会先对 or
周围的谓词进行分组和评估。最后一个谓词 $e2.field = "bar"
会使用 and
隐式联接。这样一来,评估顺序就会发生变化。
枚举类型
您可以将这些运算符与枚举类型搭配使用。它可应用于规则,以简化和优化(使用运算符而非引用列表)性能。
在以下示例中,“USER_UNCATEGORIZED”和“USER_RESOURCE_DELETION”分别对应于 15000 和 15014,因此该规则将查找所有列出的事件:
$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"
事件列表:
- USER_RESOURCE_DELETION
- USER_RESOURCE_UPDATE_CONTENT
- USER_RESOURCE_UPDATE_PERMISSIONS
- USER_STATS
- USER_UNCATEGORIZED
Nocase 修饰符
在字符串值或正则表达式之间使用比较表达式时,您可以在表达式的末尾附加 nocase,以忽略大小写。
$e.principal.hostname != "http-server" nocase
$e1.principal.hostname = $e2.target.hostname nocase
$e.principal.hostname = /dns-server-[0-9]+/ nocase
re.regex($e.target.hostname, `client-[0-9]+`) nocase
当字段类型是枚举值时,不能使用此字段。以下示例无效,并会产生编译错误:
$e.metadata.event_type = "NETWORK_DNS" nocase
$e.network.ip_protocol = "TCP" nocase
重复字段
在统一数据模型 (UDM) 中,某些字段被标记为重复,这表示它们是值列表或其他类型的消息。
重复字段和布尔值表达式
对重复字段执行操作的布尔表达式有 2 种:
- 已修改
- 未修改
请考虑以下事件:
event_original {
principal {
// ip is a repeated field
ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]
hostname: "host"
}
}
经过修改的表达式
以下部分介绍了 any
和 all
修饰符的用途以及如何在表达式中使用它们。
任意
如果重复字段的任意元素满足条件,则整个事件都满足条件。
event_original
满足any $e.principal.ip = "192.0.2.1"
。event_original
未通过any $e.repeated_field.field_a = "9.9.9.9
测试。
全部
如果重复字段的所有元素都满足条件,则整个事件也满足该条件。
event_original
满足net.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")
。event_original
未通过all $e.principal.ip = "192.0.2.2"
测试。
使用 any
或 all
编写条件时,请注意使用 not
来排除条件的含义可能与使用否定运算符不同。
例如:
not all $e.principal.ip = "192.168.12.16"
会检查是否并非所有 IP 地址都与192.168.12.16
匹配,这意味着规则会检查是否至少有一个 IP 地址与192.168.12.16
不匹配。all $e.principal.ip != "192.168.12.16"
会检查是否所有 IP 地址都与192.168.12.16
不匹配,这意味着规则会检查是否没有 IP 地址与192.168.12.16
匹配。
限制:
any
和all
运算符仅与重复字段(而非标量字段)兼容。any
和all
不能用于联接两个重复字段。例如,any $e1.principal.ip = $e2.principal.ip
无效。- 引用列表表达式不支持
any
和all
运算符。
未修改的表达式
对于未修改的表达式,重复字段中的每个元素都是单独处理的。如果事件的重复字段包含 n 个元素,则系统会对事件的 n 个副本应用该规则,其中每个副本都包含重复字段的某个元素。这些副本是暂时性的,不会存储。
该规则会应用于以下副本:
活动文案 | principal.ip | principal.hostname |
---|---|---|
event_copy_1 | "192.0.2.1" | “host” |
event_copy_2 | "192.0.2.2" | “host” |
event_copy_3 | "192.0.2.3" | “host” |
如果任何事件副本都满足重复字段上的所有未修改条件,则整个事件都满足所有条件。也就是说,如果您对重复字段设置了多个条件,则事件副本必须满足所有这些条件。以下规则示例使用前面的示例数据集来演示此行为。
以下规则在针对 event_original
示例数据集运行时会返回一个匹配项,因为 event_copy_1
满足所有事件谓词:
rule repeated_field_1 {
meta:
events:
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/8") // Checks if IP address matches 192.x.x.x
$e.principal.ip = "192.0.2.1"
condition:
$e
}
以下规则在针对 event_original
示例数据集运行时不会返回匹配项,因为 $e.principal.ip
中没有事件副本满足所有事件谓词。
rule repeated_field_2 {
meta:
events:
$e.principal.ip = "192.0.2.1"
$e.principal.ip = "192.0.2.2"
condition:
$e
}
对重复字段的修改后的表达式与对重复字段的未修改表达式兼容,因为每个事件副本的元素列表都是相同的。请考虑以下规则:
rule repeated_field_3 {
meta:
events:
any $e.principal.ip = "192.0.2.1"
$e.principal.ip = "192.0.2.3"
condition:
$e
}
该规则会应用于以下副本:
活动文案 | principal.ip | 任何 $e.principal.ip |
---|---|---|
event_copy_1 | "192.0.2.1" | ["192.0.2.1", "192.0.2.2", "192.0.2.3"] |
event_copy_2 | "192.0.2.2" | ["192.0.2.1", "192.0.2.2", "192.0.2.3"] |
event_copy_3 | "192.0.2.3" | ["192.0.2.1", "192.0.2.2", "192.0.2.3"] |
在本例中,所有副本都满足 any $e.principal.ip = "192.0.2.1"
,但只有 event_copy_3
满足 $e.principal.ip = "192.0.2.3"。因此,整个事件将匹配。
您还可以通过以下方式来理解这些表达式类型:
- 使用
any
或all
的重复字段表达式会对event_original
中的列表进行运算。 - 不使用
any
或all
的重复字段上的表达式会对各个event_copy_n
事件进行运算。
重复字段和占位符
重复字段可与占位符分配搭配使用。与对重复字段使用未修改表达式类似,系统会为每个元素创建事件的副本。使用 event_copy
的相同示例,占位符会为每个事件副本采用 event_copy_n
的重复字段值,其中 n 是事件副本编号。如果在匹配部分中使用占位符,则可能会导致出现多个匹配项。
以下示例会生成一个匹配项。$ip
占位符等于 event_copy_1
的 192.0.2.1
,这满足规则中的谓词。匹配的事件样本包含单个元素 event_original
。
// Generates 1 match.
rule repeated_field_placeholder1 {
meta:
events:
$ip = $e.principal.ip
$ip = "192.0.2.1"
$host = $e.principal.hostname
match:
$host over 5m
condition:
$e
}
以下示例会生成三个匹配项。对于每个不同的 event_copy_n
副本,$ip
占位符都等于不同的值。由于 $ip
位于匹配部分,因此系统会对其进行分组。因此,您会得到三个匹配,每个匹配的 $ip
匹配变量值都不同。每个匹配项都有相同的事件样本:单个元素 event_original
。
// Generates 3 matches.
rule repeated_field_placeholder2 {
meta:
events:
$ip = $e.principal.ip
net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x
match:
$ip over 5m
condition:
$e
}
使用分配给重复字段的占位符的结果
占位符会分配给每个重复字段的每个元素,而不是整个列表。因此,当这些元素在结果部分中使用时,系统仅会使用满足前面部分条件的元素来计算结果。
请考虑以下规则:
rule outcome_repeated_field_placeholder {
meta:
events:
$ip = $e.principal.ip
$ip = "192.0.2.1" or $ip = "192.0.2.2"
$host = $e.principal.hostname
match:
$host over 5m
outcome:
$o = array_distinct($ip)
condition:
$e
}
此规则的执行分为 4 个阶段。第 1 阶段是事件复制:
活动文案 | $ip | $host | $e |
---|---|---|---|
event_copy_1 | "192.0.2.1" | “host” | event_id |
event_copy_2 | "192.0.2.2" | “host” | event_id |
event_copy_3 | "192.0.2.3" | “host” | event_id |
然后,“事件”部分会滤除与过滤条件不匹配的行:
活动文案 | $ip | $host | $e |
---|---|---|---|
event_copy_1 | "192.0.2.1" | “host” | event_id |
event_copy_2 | "192.0.2.2" | “host” | event_id |
event_copy_3
被滤除,因为 "192.0.2.3"
不满足 $ip = "192.0.2.1" or $ip = "192.0.2.2"
。
然后,“匹配”部分将按匹配变量进行分组,而“结果”部分将对每个组执行汇总:
$host | $o | $e |
---|---|---|
“host” | ["192.0.2.1", "192.0.2.2"] | event_id |
$o = array_distinct($ip)
是使用上一个阶段(而非事件复制阶段)的 $ip
计算得出的。
最后,条件部分将过滤每个组。由于此规则仅检查 $e 是否存在,因此前面的行将产生单次检测。
$o
不包含 $e.principal.ip
中的所有元素,因为并非所有元素都满足“事件”部分中的所有条件。不过,由于事件样本使用 event_original
,因此 e.principal.ip
的所有元素都会显示在事件样本中。
数组索引
您可以对重复字段执行数组编号。如需访问第 n 个重复字段元素,请使用标准列表语法(元素从 0 开始编号)。超出范围的元素会返回默认值。
$e.principal.ip[0] = "192.168.12.16"
$e.principal.ip[999] = ""
如果元素少于 1000 个,则此值的计算结果为true
。
限制:
- 索引必须为非负整数字面量。例如,
$e.principal.ip[-1]
无效。 - 类型为
int
的值(例如设置为int
的占位符)不计入统计范围。 - 数组编号不能与
any
或all
结合使用。例如,any $e.intermediary.ip[0]
无效。 - 数组编号不能与映射语法结合使用。例如,
$e.additional.fields[0]["key"]
无效。 - 如果字段路径包含多个重复字段,则所有重复字段都必须使用数组编号。例如,
$e.intermediary.ip[0]
无效,因为intermediary
和ip
都是重复字段,但只有ip
有一个索引。
重复消息
重复使用 message
字段会导致匹配几率降低。下例对此进行了说明。
请考虑以下事件:
event_repeated_message {
// about is a repeated message field.
about {
// ip is a repeated string field.
ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]
hostname: "alice"
}
about {
hostname: "bob"
}
}
如对重复字段的未修改表达式所述,系统会为重复字段的每个元素创建事件的临时副本。请考虑以下规则:
rule repeated_message_1 {
meta:
events:
$e.about.ip = "192.0.2.1"
$e.about.hostname = "bob"
condition:
$e
}
该规则会应用于以下副本:
活动文案 | about.ip | about.hostname |
---|---|---|
event_copy_1 | "192.0.2.1" | “alice” |
event_copy_2 | "192.0.2.2" | “alice” |
event_copy_3 | "192.0.2.3" | “alice” |
event_copy_4 | "" | "bob" |
事件与规则不匹配,因为没有任何事件副本满足所有表达式。
重复消息和数组编号
在重复的消息字段上使用数组编号与未修改的表达式时,可能会发生另一种意外行为。请考虑以下使用数组编号的示例规则:
rule repeated_message_2 {
meta:
events:
$e.about.ip = "192.0.2.1"
$e.about[1].hostname = "bob"
condition:
$e
}
该规则会应用于以下副本:
活动文案 | about.ip | about[1].hostname |
---|---|---|
event_copy_1 | "192.0.2.1" | "bob" |
event_copy_2 | "192.0.2.2" | "bob" |
event_copy_3 | "192.0.2.3" | "bob" |
event_copy_4 | "" | "bob" |
由于 event_copy_1
满足 repeated_message_2
中的所有表达式,因此事件与规则匹配。
这可能会导致意外行为,因为规则 repeated_message_1
缺少数组编制索引,没有产生任何匹配,而规则 repeated_message_2
使用了数组编制索引,并产生了匹配。
评论
使用两个斜杠字符 (// comment
) 或用斜杠星号 (/* comment */
) 发出的多行注释来指定注释,就像在 C 中那样。
字面量
支持非负整数和浮点数、字符串、布尔值和正则表达式字面量。
字符串和正则表达式字面量
您可以使用以下任一引号字符将字符串括在 YARA-L 2.0 中。不过,引用文字的解释方式因所使用的文字而异。
双引号 (") - 用于普通字符串。必须包含转义字符。
例如:“hello\tworld”-\t 将被解释为一个标签页反引号 (`) - 用于按字面解释所有字符。
例如:“hello\tworld”-\t 不会被解释为标签页
对于正则表达式,您有两种选择。
如果您想在不使用 re.regex()
函数的情况下直接使用正则表达式,请使用 /regex/
作为正则表达式字面量。
使用 re.regex()
函数时,您还可以使用字符串字面量作为正则表达式字面量。请注意,对于双引号字符串字面量,您必须用反斜杠字符转义反斜杠字符,这看起来很奇怪。
例如,以下正则表达式是等效的:
re.regex($e.network.email.from, `.*altostrat\.com`)
re.regex($e.network.email.from, ".*altostrat\\.com")
$e.network.email.from = /.*altostrat\.com/
Google 建议对正则表达式中的字符串使用英文反引号字符,以便于阅读。
运算符
您可以在 YARA-L 中使用以下运算符:
运算符 | 说明 |
= | 等于/声明 |
!= | 不等于 |
< | 小于 |
<= | 小于或等于 |
> | 大于 |
>= | 大于或等于 |
变量
在 YARA-L 2.0 中,所有变量均表示为 $<variable name>
。
您可以定义以下类型的变量:
事件变量 - 以归一化形式 (UDM) 或实体事件表示事件组。在
events
部分指定事件变量的条件。您可以使用名称、事件来源和事件字段来标识事件变量。允许的来源为udm
(用于规范化事件)和graph
(用于实体事件)。如果省略来源,则udm
设置为默认来源。事件字段表示为 .<field name> 链(例如 $e.field1.field2)。事件字段链始终从顶级来源(UDM 或实体)开始。匹配变量 - 在
match
部分声明。匹配变量会成为查询的分组字段,因为对于每组唯一的匹配变量(以及每个时间范围),都会返回一行。当规则找到匹配项时,将返回匹配变量值。指定每个匹配变量在events
部分中表示的内容。占位符变量 - 在
events
部分声明和定义。占位符变量与匹配变量类似。不过,您可以使用condition
部分中的占位符变量来指定匹配条件。
使用匹配变量和占位符变量可以通过传递联接条件来声明事件字段之间的关系(请参阅事件部分语法了解更多详情)。
关键字
YARA-L 2.0 中的关键字不区分大小写。例如,and
或 AND
是等效的。变量名称不得与关键字冲突。例如,$AND
或 $outcome
无效。
以下是检测引擎规则的关键字:rule
、meta
、match
、over
、events
、condition
、outcome
、options
、and
、or
、not
、nocase
、in
、regex
、cidr
、before
、after
、all
、any
、if
、max
、min
、sum
、array
、array_distinct
、count
、count_distinct
、is
和 null
。
地图
YARA-L 支持对结构体和标签的映射访问。
结构体和标签
某些 UDM 字段使用 Struct 或 Label 数据类型。
如需同时在结构体和标签中搜索特定键值对,请使用标准映射语法:
// A Struct field.
$e.udm.additional.fields["pod_name"] = "kube-scheduler"
// A Label field.
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"
映射访问始终会返回字符串。
支持的支持请求
“事件和结果”部分
// Using a Struct field in the events section
events:
$e.udm.additional.fields["pod_name"] = "kube-scheduler"
// Using a Label field in the outcome section
outcome:
$value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
向占位符分配映射值
$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
在联接条件中使用映射字段
// using a Struct field in a join condition between two udm events $u1 and $u2
$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]
不支持的情况
以下情况不支持地图。
将 any
或 all
关键字与地图结合使用
例如,以下内容不受支持:
all $e.udm.additional.fields["pod_name"] = "kube-scheduler"
其他类型的值
映射语法只能返回字符串值。对于 Struct 数据类型,映射语法只能访问值为字符串的键。无法访问值为其他基元类型(如整数)的键。
重复值处理
映射访问始终返回单个值。在极少数情况下,映射访问可能引用多个值,在这种情况下,映射访问将确定性地返回第一个值。
这可能发生在以下任一情况下:
标签具有重复的键。
标签结构表示映射,但不会强制执行键唯一性。 根据惯例,映射应具有唯一的键,因此 Google Security Operations 不建议使用重复的键填充标签。
如果对以下数据示例运行规则文本
$e.metadata.ingestion_labels["dupe-key"]
,则会返回第一个可能的值val1
:// Disrecommended usage of label with a duplicate key: event { metadata{ ingestion_labels{ key: "dupe-key" value: "val1" // This is the first possible value for "dupe-key" } ingestion_labels{ key: "dupe-key" value: "val2" } } }
标签具有祖先重复字段。
重复字段可以将标签作为子字段包含在内。顶级重复字段中的两个不同条目可能包含具有相同键的标签。如果对以下数据示例运行规则文本
$e.security_result.rule_labels["key"]
,则会返回第一个可能的值val3
:event { // security_result is a repeated field. security_result { threat_name: "threat1" rule_labels { key: "key" value: "val3" // This is the first possible value for "key" } } security_result { threat_name: "threat2" rule_labels { key: "key" value: "val4" } } }
Functions
本部分介绍了您可以在检测引擎规则和搜索中使用的 YARA-L 2.0 函数。
这些函数可用于 YARA-L 规则的以下部分:
events
部分。- 结果部分中条件的
BOOL_CLAUSE
。
arrays.concat
arrays.concat(string_array, string_array)
说明
通过从原始字符串数组复制元素来返回新的字符串数组。
参数数据类型
ARRAY_STRINGS
,ARRAY_STRINGS
返回类型
ARRAY_STRINGS
代码示例
示例 1
以下示例会串联两个不同的字符串数组。
arrays.concat(["test1", "test2"], ["test3"]) = ["test1", "test2", "test3"]
示例 2
以下示例将数组与空字符串串联。
arrays.concat([""], [""]) = ["", ""]
示例 3
以下示例会串联空数组。
arrays.concat([], []) = []
arrays.join_string
arrays.join_string(array_of_strings, optional_delimiter)
说明
将字符串数组转换为由可选参数分隔的单个字符串。如果未提供分隔符,则使用空字符串。
参数数据类型
ARRAY_STRINGS
,STRING
返回类型
STRING
代码示例
以下是该函数的使用示例:
示例 1
以下示例会联接包含非 null 元素和分隔符的数组。
arrays.join_string(["foo", "bar"], ",") = "foo,bar"
示例 2
以下示例将数组与 null 元素和分隔符联接起来。
arrays.join_string(["foo", NULL, "bar"], ",") = "foo,bar"
示例 3
以下示例会联接一个包含非 null 元素且不含分隔符的数组。
arrays.join_string(["foo", "bar"]) = "foobar"
arrays.length
arrays.length(repeatedField)
说明
返回重复字段元素的数量。
参数数据类型
LIST
返回类型
NUMBER
代码示例
示例 1
返回重复字段元素的数量。
arrays.length($e.principal.ip) = 2
示例 2
如果路径中存在多个重复字段,则返回重复字段元素的总数。
arrays.length($e.intermediary.ip) = 3
arrays.max
arrays.max(array_of_ints_or_floats)
说明
返回数组中的最大元素,如果数组为空,则返回零。
参数数据类型
ARRAY_INTS|ARRAY_FLOATS
返回类型
FLOAT
代码示例
以下是该函数的使用示例:
示例 1
此示例会返回整数数组中的较大元素。
arrays.max([10, 20]) = 20.000000
示例 2
此示例会返回浮点数数组中的较大元素。
arrays.max([10.000000, 20.000000]) = 20.000000
arrays.min
arrays.min(array_of_ints_or_floats[, ignore_zeros=false])
说明
返回数组中最小的元素,如果数组为空,则返回零。如果第二个可选参数设置为 true,系统会忽略等于零的元素。
参数数据类型
ARRAY_INTS|ARRAY_FLOATS
,BOOL
返回类型
FLOAT
代码示例
以下是该函数的使用示例:
示例 1
以下示例会返回整数数组中最小的元素。
arrays.min([10, 20]) = 10.000000
示例 2
以下示例会返回浮点数组中最小的元素。
arrays.min([10.000000, 20.000000]) = 10.000000
示例 3
此示例会返回浮点数组中最小的元素,同时忽略零值。
arrays.min([10.000000, 20.000000, 0.0], true) = 10.000000
arrays.size
arrays.size( array )
说明
返回数组的大小。如果数组为空,则返回 0。
参数数据类型
ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS
返回类型
INT
代码示例
示例 1
此示例使用包含两个元素的字符串数组。
arrays.size(["test1", "test2"]) = 2
示例 2
此示例使用包含 3 个元素的 int 数组。
arrays.size([1, 2, 3]) = 3
示例 3
此示例使用包含 1 个元素的浮点数组
arrays.size([1.200000]) = 1
示例 4
此示例使用空数组。
arrays.size([]) = 0
arrays.index_to_float
arrays.index_to_float(array, index)
说明
返回数组中指定索引处的元素。系统会以浮点值的形式返回该索引处的元素。
索引是一个整数值,表示元素在数组中的位置。默认情况下,数组的第一个元素的索引为 0,最后一个元素的索引为 n-1,其中 n 是数组的大小。负索引允许访问相对于数组结尾的数组元素。例如,索引 -1 表示数组中的最后一个元素,索引 -2 表示数组中的倒数第二个元素。
参数数据类型
ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS
,INT
返回类型
FLOAT
代码示例
示例 1
以下示例从一个浮点数组中提取索引为 1 的元素。
arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 1) // 2.1
示例 2
以下示例从一个浮点数组中提取索引为 -1 的元素。
arrays.index_to_float([1.2, 2.1, 3.5, 4.6], -1) // 4.6
示例 3
以下示例会提取大于数组大小的索引的元素。
arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 6) // 0.0
示例 4
以下示例会从空数组中提取元素。
arrays.index_to_float([], 0) // 0.0
示例 5
以下示例会从字符串数组中提取索引为 1 的元素。
arrays.index_to_float(["1.2", "3.3", "2.4"], 1) // 3.3
示例 6
以下示例从整数数组中提取索引为 2 的元素。
arrays.index_to_float([1, 3, 2], 2) // 2.0
arrays.index_to_int
arrays.index_to_int(array_of_inputs, index)
说明
以整数形式返回数组中指定索引处的值。
索引是一个整数值,表示元素在数组中的位置。默认情况下,数组的第一个元素的索引为 0,最后一个元素的索引为 n-1,其中 n 是数组的大小。负索引允许访问相对于数组结尾的数组元素。例如,索引 -1 表示数组中的最后一个元素,索引 -2 表示数组中的倒数第二个元素。
参数数据类型
ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS
,INT
返回类型
INT
代码示例
示例 1
如果索引处的值是非数字字符串,此函数调用会返回 0。
arrays.index_to_int(["str0", "str1", "str2"], 1) = 0
示例 2
此函数会返回索引为 -1 的元素。
arrays.index_to_int(["44", "11", "22", "33"], -1) = 33
示例 3
对于超出边界的元素,返回 0。
arrays.index_to_int(["44", "11", "22", "33"], 5) = 0
示例 4
此函数会从索引为 1 的浮点数组中提取元素。
arrays.index_to_int([1.100000, 1.200000, 1.300000], 1) = 1
示例 5
此函数会从索引为 0 的 int 数组中提取元素。
arrays.index_to_int([1, 2, 3], 0) = 1
arrays.index_to_str
arrays.index_to_str(array, index)
说明
以字符串形式返回数组中指定索引处的元素。 索引是一个整数值,表示数组中元素的位置。默认情况下,数组的第一个元素的索引为 0,最后一个元素的索引为 n-1,其中 n 是数组的大小。负索引允许从数组的末尾访问数组元素。例如,索引 -1 表示数组中的最后一个元素,索引 -2 表示数组中的倒数第二个元素。
参数数据类型
ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS
,INT
返回类型
STRING
代码示例
示例 1
以下示例从字符串数组中提取索引为 1 的元素。
arrays.index_to_str(["test1", "test2", "test3", "test4"], 1) // "test2"
示例 2
以下示例从字符串数组中提取索引为 -1(数组的最后一个元素)的元素。
arrays.index_to_str(["test1", "test2", "test3", "test4"], -1) // "test4"
示例 3
以下示例会提取大于数组大小的索引的元素,并返回空字符串。
arrays.index_to_str(["test1", "test2", "test3", "test4"], 6) // ""
示例 4
以下示例会从空数组中提取元素。
arrays.index_to_str([], 0) // ""
示例 5
以下示例从一个浮点数组中提取索引为 0 的元素。输出会以字符串的形式返回。
arrays.index_to_str([1.200000, 3.300000, 2.400000], 0) // "1.2"
示例 6
以下示例从整数数组中提取索引为 2 的元素。输出为字符串形式。
arrays.index_to_str([1, 3, 2], 2) // "2"
cast.as_bool
cast.as_bool(string_or_int)
说明
函数用于将 int 或字符串值转换为布尔值。包含无法转换的值的函数调用将返回 FALSE。仅当整数为 1 且不区分大小写的字符串为“true”时,才会返回 TRUE。
参数数据类型
INT|STRING
返回类型
BOOL
代码示例
示例 1
以下示例展示了如何将非布尔值字符串转换为布尔值
cast.as_bool("123") = false
示例 2
真值整数 (1)
cast.as_bool(1) = true
示例 3
真值字符串
cast.as_bool("true") = true
示例 4
大写的真值字符串
cast.as_bool("TRUE") = true
示例 5
负整数
cast.as_bool(-1) = false
示例 6
假整数 (0)
cast.as_bool(0) = false
示例 7
空字符串
cast.as_bool("") = false
cast.as_float
cast.as_float(string_to_cast)
说明
将数字字符串转换为浮点数。任何包含无法转换的值的函数调用都会返回 0。浮点数的精度最多可保留 7 位小数。
参数数据类型
STRING
返回类型
FLOAT
代码示例
示例 1
对非数字字符串进行类型转换会返回 0。
cast.as_float("str") = 0.0000000
示例 2
对空字符串进行类型转换会返回 0。
cast.as_float("") = 0.0000000
示例 3
对有效的数字字符串进行类型转换会返回一个浮点值。
cast.as_float("1.012345678") = 1.0123456
指纹
hash.fingerprint2011(byteOrString)
说明
此函数用于计算输入字节序列或字符串的 fingerprint2011
哈希值。此函数会返回 [2, 0xFFFFFFFFFFFFFFFF]
范围内的无符号 INT
值。
参数数据类型
BTYE
,STRING
返回类型
INT
代码示例
id_fingerprint = hash.fingerprint2011("user123")
群组
group(field1, field2, field3, ...)
说明
将类型相似的字段归为一组,并将其作为占位符变量。
在 UDM 搜索中,分组字段用于跨类型相似的多个字段进行搜索。组函数与分组字段类似,但它允许您选择要组合在一起以触发检测的字段。您可以使用 group 函数跨不同的名词类型收集有关特定实体(例如主机名、IP 地址或用户 ID)的信息。
代码示例
示例 1
将所有 IP 地址归为一组,并按扫描时间范围内出现次数从高到低的顺序提供最常见 IP 地址的计数。
$ip = group(principal.ip, about.ip, target.ip)
$ip != ""
match:
$ip
outcome:
$count = count_distinct(metadata.id)
order:
$count desc
hash.sha256
hash.sha256(string)
说明
返回输入字符串的 SHA-256 哈希值。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
以下示例显示了当输入有效字符串时生成的 SHA-256 哈希。
hash.sha256("str") = "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a"
示例 2
此示例显示了当输入为空字符串时生成的 SHA-256 哈希值。
hash.sha256("") = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
math.abs
math.abs(numericExpression)
说明
返回整数或浮点数表达式的绝对值。
参数数据类型
NUMBER
返回类型
NUMBER
代码示例
示例 1
如果事件距离指定时间(自 Unix 纪元至今的时间,以秒为单位)超过 5 分钟,则无论事件是发生在指定时间之前还是之后,以下示例都会返回 True。对 math.abs
的调用不能依赖于多个变量或占位符。例如,您无法将以下示例中硬编码的时间值 1643687343 替换为 $e2.metadata.event_timestamp.seconds
。
300 < math.abs($e1.metadata.event_timestamp.seconds - 1643687343)
math.ceil
math.ceil(number)
说明
返回不小于给定数字的最小整数(向上取整)。如果输入为 null 或太大而无法放入 int64 中,则返回 0。
参数数据类型
FLOAT
返回类型
INT
代码示例
本部分包含使用 math.ceil
的示例。
示例 1
此示例会返回一个整数的上限。
math.ceil(2.000000) = 2
示例 2
此示例会返回负数的 Ceil 值。
math.ceil(-1.200000) = -1
示例 3
此示例将一个超出 64 位整数范围的数字的 Ceil 值返回为 0。
math.ceil(184467440737095516160.0) = 0
math.floor
math.floor(float_val)
说明
返回不大于所提供值的最大整数值(向下舍入)。如果输入为 null 或太大而无法放入 int64,则返回 0。
参数数据类型
FLOAT
返回类型
INT
代码示例
示例 1
此示例展示了正数情形。
math.floor(1.234568) = 1
示例 2
此示例展示了负数情况。
math.floor(-1.234568) = -2
示例 3
此示例显示了零个用例。
math.floor(0.000000) = 0
math.geo_distance
math.geo_distance(longitude1, latitude1, longitude2, latitude2))
说明
返回两个地理位置(坐标)之间的距离。如果地理坐标无效,则返回 -1。
参数数据类型
FLOAT
、FLOAT
、FLOAT
、FLOAT
返回类型
FLOAT
代码示例
示例 1
此示例在所有参数均为有效坐标时返回距离。
math.geo_distance(-122.020287, 37.407574, -122.021810, 37.407574) = 134.564318
示例 2
此示例展示了当其中一个参数是截断坐标时,如何返回距离。
math.geo_distance(-122.000000, 37.407574, -122.021810, 37.407574) = 1926.421905
示例 3
在本示例中,如果其中一个参数是无效的坐标,则会返回 -1。
math.geo_distance(-122.897680, 37.407574, -122.021810, 97.407574) = -1.000000
示例 4
在本示例中,如果坐标相同,则返回 0。
math.geo_distance(-122.897680, 37.407574, -122.897680, 37.407574) = 0.000000
math.is_increasing
math.is_increasing(num1, num2, num3)
说明
接受一个数字值(整数或双精度值)列表,如果值按升序排列,则返回 True
;否则返回 False
。
参数数据类型
INT|FLOAT
、INT|FLOAT
、INT|FLOAT
返回类型
BOOL
代码示例
示例 1
此示例包含以秒为单位的时间戳类似值。
math.is_increasing(1716769112, 1716769113, 1716769114) = true
示例 2
此示例包含一个负实数、一个零 INT64 值和一个正 INT64 值。
math.is_increasing(-1.200000, 0, 3) = true
示例 3
此示例包含一个负实数、一个零 INT64 和一个负 INT64 值。
math.is_increasing(-1.200000, 0, -3) = false
示例 4
此示例包含两个负双精度值和一个零 INT64 值。
math.is_increasing(-1.200000, -1.50000, 0) = false
示例 5
此示例包含一个负数双精度值和两个相同的值。
math.is_increasing(-1.200000, 0, 0) = false
math.log
math.log(numericExpression)
说明
返回整数或浮点表达式的自然对数值。
参数数据类型
NUMBER
返回类型
NUMBER
代码示例
示例 1
math.log($e1.network.sent_bytes) > 20
math.pow
math.pow(base, exponent)
说明
返回第一个参数的第二个参数次幂的值。如果发生溢出,则返回 0。
参数数据类型
底数:INT|FLOAT
指数:INT|FLOAT
返回类型
FLOAT
代码示例
示例 1
以下示例展示了整数情况。
math.pow(2, 2) // 4.00
示例 2
以下示例展示了分数基准情况。
math.pow(2.200000, 3) // 10.648
示例 3
此示例展示了分数基数和指数情况。
math.pow(2.200000, 1.200000) // 2.575771
示例 4
此示例展示了负功率情况。
math.pow(3, -3) // 0.037037
示例 5
此示例展示了分数幂的情况。
math.pow(3, -1.200000) // 0.267581
示例 6
此示例展示了一个负例基准情况。
math.pow(-3, -3) // -0.037037
示例 7
此示例显示了基准为零的情况。
math.pow(0, 3) // 0
示例 8
此示例显示了零功率情形。
math.pow(9223372036854775807, 0) // 1
示例 9
此示例展示了一个大基数情况。
math.pow(9223372036854775807, 1.200000) // 57262152889751593549824
math.random
math.random()
说明
在范围 [0, 1)
(包含 0,不包含 1)内生成 DOUBLE 类型的伪随机值。
返回类型
FLOAT
代码示例
以下示例会检查随机值是否在 [0, 1)
范围内。none
if(math.random() >= 0 and math.random() < 1) = true
math.round
math.round(numericExpression, decimalPlaces)
说明
返回舍入到最接近的整数或指定小数位数的值。
参数数据类型
NUMBER
返回类型
NUMBER
代码示例
math.round(10.7) // returns 11
math.round(1.2567, 2) // returns 1.25
math.round(-10.7) // returns -11
math.round(-1.2) // returns -1
math.round(4) // returns 4, math.round(integer) returns the integer
math.sqrt
math.sqrt(number)
说明
返回给定数的平方根。如果是负数,则返回 0。
参数数据类型
INT|FLOAT
返回类型
FLOAT
代码示例
示例 1
此示例会返回 int 参数的平方根。
math.sqrt(3) = 1.732051
示例 2
此示例返回负整数参数的平方根。
math.sqrt(-3) = 0.000000
示例 3
此示例会返回零参数的平方根。
math.sqrt(0) = 0.000000
示例 4
此示例会返回浮点参数的平方根。
math.sqrt(9.223372) = 3.037000
示例 5
此示例会返回负浮点参数的平方根。
math.sqrt(-1.200000) = 0.000000
指标
指标函数可以汇总大量历史数据。您可以在规则的“结果”部分使用 metrics.functionName()
来使用此属性。
如需了解详情,请参阅 YARA-L 指标。
net.ip_in_range_cidr
net.ip_in_range_cidr(ipAddress, subnetworkRange)
说明
如果给定 IP 地址在指定的子网内,则返回 true
。
您可以使用 YARA-L 通过 net.ip_in_range_cidr()
语句搜索子网内所有 IP 地址中的 UDM 事件。支持使用 IPv4 和 IPv6。
如需在 IP 地址范围中搜索,请指定 IP UDM 字段和 CIDR 范围。YARA-L 可以处理单数和重复 IP 地址字段。
如需在 IP 地址范围中搜索,请指定 ip
UDM 字段和无类别域间路由 (CIDR) 范围。YARA-L 可以处理单数和重复 IP 地址字段。
参数数据类型
STRING
,STRING
返回类型
BOOL
代码示例
示例 1
IPv4 示例:
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")
示例 2
IPv6 示例:
net.ip_in_range_cidr($e.network.dhcp.yiaddr, "2001:db8::/32")
如需查看使用 net.ip_in_range_cidr()
语句的示例规则,请参阅IP 地址范围内的单个事件中的示例规则。)
re.regex
您可以在 YARA-L 2.0 中使用以下任一语法定义正则表达式匹配:
使用 YARA-L 语法 - 与事件相关。以下是此语法的通用表示形式:
$e.field = /regex/
使用 YARA-L 语法 - 作为接受以下参数的函数:
- 应用正则表达式的字段。
- 以字符串指定的正则表达式。
以下是此语法的通用表示形式:
re.regex($e.field, `regex`)
说明
如果字符串包含与所提供正则表达式匹配的子字符串,则此函数会返回 true
。无需在正则表达式的开头或结尾添加 .*
。
备注
- 如需匹配确切的字符串,或仅匹配前缀或后缀,请在正则表达式中添加
^
(开头)和$
(结尾)定位字符。例如,/^full$/
与"full"
完全匹配,而/full/
可以与"fullest"
、"lawfull"
和"joyfully"
匹配。 - 如果 UDM 字段包含换行符,则
regexp
仅匹配 UDM 字段的第一行。如需强制执行完整的 UDM 字段匹配,请将(?s)
添加到正则表达式。例如,将/.*allUDM.*/
替换为/(?s).*allUDM.*/
。 - 您可以在字符串之后使用
nocase
修饰符,以指示搜索应忽略大小写。
参数数据类型
STRING
,STRING
参数表达式类型
ANY
,ANY
返回类型
BOOL
代码示例
示例 1
// Equivalent to $e.principal.hostname = /google/
re.regex($e.principal.hostname, "google")
re.capture
re.capture(stringText, regex)
说明
使用参数中提供的正则表达式模式从字符串捕获(提取)数据。
此函数接受两个参数:
stringText
:要搜索的原始字符串。regex
:指示要搜索的模式的正则表达式。
正则表达式可以在括号中包含 0 或 1 个捕获组。如果正则表达式包含 0 个捕获组,则该函数返回第一个整个匹配的子字符串。如果正则表达式包含 1 个捕获组,则它将返回捕获组的第一个匹配的子字符串。定义两个或多个捕获组会返回编译器错误。
参数数据类型
STRING
,STRING
返回类型
STRING
代码示例
示例 1
在以下示例中,如果 $e.principal.hostname
包含“aaa1bbaa2”,则该示例为 True,因为此函数会返回第一个实例。此示例不包含捕获组。
"aaa1" = re.capture($e.principal.hostname, "a+[1-9]")
示例 2
以下示例会捕获电子邮件地址中 @ 符号后面的所有内容。如果 $e.network.email.from
字段为 test@google.com
,则示例会返回 google.com
。以下示例包含一个捕获组。
"google.com" = re.capture($e.network.email.from , "@(.*)")
示例 3
如果正则表达式与文本中的任何子字符串都不匹配,则该函数会返回空字符串。排除空字符串使您可以省略没有发生匹配的事件,这在使用 re.capture()
和“不等于”运算时尤其重要:
// Exclude the empty string to omit events where no match occurs.
"" != re.capture($e.network.email.from , "@(.*)")
// Exclude a specific string with an inequality.
"google.com" != re.capture($e.network.email.from , "@(.*)")
re.replace
re.replace(stringText, replaceRegex, replacementText)
说明
执行正则表达式替换。
此函数接受三个参数:
stringText
:原始字符串。replaceRegex
:指示要搜索的模式的正则表达式。replacementText
:要插入到每个匹配项中的文本。
返回源自原始 stringText
的新字符串,其中与 replaceRegex
中的模式匹配的所有子字符串都会替换为 replacementText
中的值。您可以在 replacementText
中使用通过反斜杠转义的数字(\1
到 \9
),将与带有英文括号的对应组匹配的文本插入到 replaceRegex
模式中。使用 \0
可引用整个匹配文本。
该函数会替换非重叠的匹配项,并优先替换第一个找到的出现项。例如,re.replace("banana", "ana", "111")
会返回字符串“b111na”。
参数数据类型
STRING
、STRING
、STRING
返回类型
STRING
代码示例
示例 1
以下示例会捕获电子邮件地址中 @
符号后面的所有内容,将 com
替换为 org
,然后返回结果。请注意使用嵌套函数。
"email@google.org" = re.replace($e.network.email.from, "com", "org")
示例 2
以下示例在 replacementText
参数中使用反斜杠转义数字来引用 replaceRegex
模式的匹配项。
"test1.com.google" = re.replace(
$e.principal.hostname, // holds "test1.test2.google.com"
"test2\.([a-z]*)\.([a-z]*)",
"\\2.\\1" // \\1 holds "google", \\2 holds "com"
)
示例 3
在处理空字符串和 re.replace()
时,请注意以下情况:
使用空字符串作为 replaceRegex
:
// In the function call below, if $e.principal.hostname contains "name",
// the result is: 1n1a1m1e1, because an empty string is found next to
// every character in `stringText`.
re.replace($e.principal.hostname, "", "1")
如需替换空字符串,您可以使用 "^$"
作为 replaceRegex
:
// In the function call below, if $e.principal.hostname contains the empty
// string, "", the result is: "none".
re.replace($e.principal.hostname, "^$", "none")
sample_rate
optimization.sample_rate(byteOrString, rateNumerator, rateDenominator)
说明
此函数会根据确定性抽样策略确定是否要包含事件。此函数会返回:
true
表示输入值的一部分,相当于 (rateNumerator
/rateDenominator
),表示应将该事件纳入样本中。false
,表示不应将相应事件包含在样本中。
如果您只想处理部分事件,此函数非常有用。等同于:
hash.fingerprint2011(byteOrString) % rateDenominator < rateNumerator
参数数据类型
- byteOrString:计算结果为
BYTE
或STRING
的表达式。 - rateNumerator:'INT'
- rateDenominator: 'INT'
返回类型
BOOL
代码示例
events:
$e.metadata.event_type = "NETWORK_CONNECTION"
$asset_id = $e.principal.asset.asset_id
optimization.sample_rate($e.metadata.id, 1, 5) // Only 1 out of every 5 events
match:
$asset_id over 1h
outcome:
$event_count = count_distinct($e.metadata.id)
// estimate the usage by multiplying by the inverse of the sample rate
$usage_past_hour = sum(5.0 * $e.network.sent_bytes)
condition:
// Requiring a certain number of events after sampling avoids bias (e.g. a
// device with just 1 connection will still show up 20% of the time and
// if we multiply that traffic by 5, we'll get an incorrect estimate)
$e and ($usage_past_hour > 1000000000) and $event_count >= 100
strings.base64_decode
strings.base64_decode(encodedString)
说明
返回包含编码字符串的 base64 解码版本的字符串。
此函数接受一个 base64 编码的字符串作为参数。如果 encodedString
不是有效的 base64 编码字符串,则此函数会原样返回 encodedString
。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
"test" = strings.base64_decode($e.principal.domain.name)
strings.coalesce
strings.coalesce(a, b, c, ...)
说明
此函数接受无限数量的参数,并返回第一个不计算为空字符串的表达式的值(例如“非零值”)。如果所有参数的计算结果均为空字符串,则函数调用会返回空字符串。
参数可以是字面量、事件字段或函数调用。所有参数都必须为 STRING
类型。如果任何参数都是事件字段,则这些属性必须来自同一事件。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
以下示例包含字符串变量作为参数。当 (1) $e.network.email.from
为 suspicious@gmail.com
或 (2) $e.network.email.from
为空且 $e.network.email.to
为 suspicious@gmail.com
时,该条件的计算结果为 true。
"suspicious@gmail.com" = strings.coalesce($e.network.email.from, $e.network.email.to)
示例 2
以下示例会调用具有多个参数的 coalesce
函数。此条件会将事件 $e
中的第一个非 null IP 地址与参考列表 ip_watchlist
中的值进行比较。在此调用中合并参数的顺序与在规则条件中枚举参数的顺序相同:
- 系统会先评估
$e.principal.ip
。 - 接下来,系统会评估
$e.src.ip
。 - 接下来,系统会评估
$e.target.ip
。 - 最后,如果前面的
ip
字段未设置,系统会将字符串“No IP”作为默认值返回。
strings.coalesce($e.principal.ip, $e.src.ip, $e.target.ip, "No IP") in %ip_watchlist
示例 3
以下示例尝试合并来自事件 $e1
和事件 $e2
的 principal.hostname
。该示例会返回编译器错误,因为参数是不同的事件变量。
// returns a compiler error
"test" = strings.coalesce($e1.principal.hostname, $e2.principal.hostname)
strings.concat
strings.concat(a, b, c, ...)
说明
返回任意数量项的串联,每个项可以是字符串、整数或浮点数。
如果任何参数都是事件字段,则这些属性必须来自同一事件。
参数数据类型
STRING
、FLOAT
、INT
返回类型
STRING
代码示例
示例 1
以下示例包含字符串变量和整数变量作为参数。principal.hostname
和 principal.port
来自同一事件 $e
,并串联在一起以返回字符串。
"google:80" = strings.concat($e.principal.hostname, ":", $e.principal.port)
示例 2
以下示例包含字符串变量和字符串字面量作为参数。
"google-test" = strings.concat($e.principal.hostname, "-test") // Matches the event when $e.principal.hostname = "google"
示例 3
以下示例包含字符串变量和浮点字面量作为参数。以字符串表示时,整数浮点数的格式不带小数点(例如,1.0 表示为“1”)。此外,小数点后超过 16 位数的浮点数会被截断为小数点后 16 位。
"google2.5" = strings.concat($e.principal.hostname, 2.5)
示例 4
以下示例包含字符串变量、字符串字面量、整数变量和浮点字面量作为参数。所有变量都来自同一事件 $e
,并与字面量串联在一起以返回字符串。
"google-test802.5" = strings.concat($e.principal.hostname, "-test", $e.principal.port, 2.5)
示例 5
以下示例尝试将来自事件 $e1
的 principal.port 与来自事件 $e2
的 principal.hostname
串联。该示例会返回编译器错误,因为参数是不同的事件变量。
// Will not compile
"test" = strings.concat($e1.principal.port, $e2.principal.hostname)
strings.contains
strings.contains( str, substr )
说明
如果给定字符串包含指定的子字符串,则返回 true。否则,它将返回 false。
参数数据类型
STRING
,STRING
返回类型
BOOL
代码示例
示例 1
由于字符串包含子字符串“is”,因此此示例会返回 true。
strings.contains("thisisastring", "is") = true
示例 2
此示例会返回 false,因为字符串不包含子字符串“that”。
strings.contains("thisisastring", "that") = false
strings.count_substrings
strings.count_substrings(string_to_search_in, substring_to_count)
说明
给定一个字符串和一个子字符串后,返回字符串中子字符串的非重叠出现次数的 int64 值。
参数数据类型
STRING
,STRING
返回类型
INT
代码示例
本部分包含计算给定字符串中子字符串出现次数的示例。
示例 1
此示例使用非 null 字符串和非 null 单个子字符串字符。
strings.count_substrings("this`string`has`four`backticks", "`") = 4
示例 2
此示例使用非 null 字符串和长度大于 1 个字符的非 null 子字符串。
strings.count_substrings("str", "str") = 1
示例 3
此示例使用非 null 字符串和空子字符串。
strings.count_substrings("str", "") = 0
示例 4
此示例使用空字符串和一个大于一个字符的非 null 子字符串。
strings.count_substrings("", "str") = 0
示例 5
此示例使用空字符串和空子字符串。
strings.count_substrings("", "") = 0
示例 6
此示例使用一个非 null 字符串和一个大于一个字符且出现次数大于 1 次的非 null 子字符串。
strings.count_substrings("fooABAbarABAbazABA", "AB") = 3
示例 7
此示例使用一个非 null 字符串和一个大于一个字符且出现次数大于 1 次的非 null 子字符串。它突出显示了重叠子字符串出现情况的限制
strings.count_substrings("ABABABA", "ABA") = 2
strings.extract_domain
strings.extract_domain(url_string)
说明
从字符串中提取网域。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
此示例显示了一个空字符串
strings.extract_domain("") = ""
示例 2
随机字符串,不是网址
strings.extract_domain("1234") = ""
示例 3
多次回车
strings.extract_domain("\\\\") = ""
示例 4
妥善处理非字母字符
strings.extract_domain("http://例子.卷筒纸.中国") = "卷筒纸.中国"
示例 5
处理 URI
strings.extract_domain("mailto:?to=&subject=&body=") = ""
示例 6
实际网址前有多个字符
strings.extract_domain(" \t !$5*^)&dahgsdfs;http://www.google.com") = "google.com"
示例 7
URI #
中的特殊字符
strings.extract_domain("test#@google.com") = ""
示例 8
网址 #
中包含特殊字符
strings.extract_domain("https://test#@google.com") = ""
示例 9
正例测试用例
strings.extract_domain("https://google.co.in") = "google.co.in"
strings.extract_hostname
strings.extract_hostname(string)
说明
从字符串中提取主机名。此函数区分大小写。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
此示例会返回一个空字符串。
strings.extract_hostname("") = ""
示例 2
随机字符串,不是网址
strings.extract_hostname("1234") = "1234"
示例 3
多个反斜杠
strings.extract_hostname("\\\\") = ""
示例 4
妥善处理非英文字符
strings.extract_hostname("http://例子.卷筒纸.中国") = "例子.卷筒纸.中国"
示例 5
处理 URI
strings.extract_hostname("mailto:?to=&subject=&body=") = "mailto"
示例 6
实际网址前有多个字符
strings.extract_hostname(" \t !$5*^)&dahgsdfs;http://www.google.com") = "www.google.com"
示例 7
URI #
中的特殊字符
strings.extract_hostname("test#@google.com") = "test"
示例 8
网址 #
中包含特殊字符
strings.extract_hostname("https://test#@google.com") = "test"
strings.from_hex
strings.from_hex(hex_string)
说明
返回与给定十六进制字符串关联的字节。
参数数据类型
STRING
返回类型
BYTES
代码示例
获取与给定十六进制字符串关联的字节。
示例 1
以下示例展示了非十六进制字符转换。
strings.from_hex("str") // returns empty bytes
示例 2
以下示例显示了包含空字符串的输入。
strings.from_hex("") // returns empty bytes
示例 3
以下示例展示了十六进制字符串转换。
strings.from_hex("1234") // returns 1234 bytes
示例 4
以下示例展示了非 ASCII 字符转换。
strings.from_hex("筒纸.中国") // returns empty bytes
strings.ltrim
strings.ltrim(string_to_trim, cutset)
说明
从给定字符串中剪除前导空格。此函数会移除该切片集中的前导字符。
参数数据类型
STRING
,STRING
返回类型
STRING
代码示例
以下是示例用例。
示例 1
此示例使用相同的第一个和第二个参数。
strings.ltrim("str", "str") = ""
示例 2
此示例使用空字符串作为第二个参数。
strings.ltrim("str", "") = "str"
示例 3
此示例使用空字符串作为第一个参数,并使用字符串作为第二个参数。
strings.ltrim("", "str") = ""
示例 4
此示例使用包含空格的字符串,并将字符串用作第二个参数。
strings.ltrim("a aastraa aa ", " a") = "straa aa "
strings.reverse
strings.reverse(STRING)
说明
返回输入字符串的反向字符串。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
以下示例传递一个短字符串。
strings.reverse("str") = "rts" // The function returns 'rts'.
示例 2
以下示例传递了一个空字符串。
strings.reverse("") = ""
示例 3
以下示例传递了回文。
strings.reverse("tacocat") = "tacocat"
strings.rtrim
strings.rtrim(string_to_trim, cutset)
说明
从给定字符串中剪除尾随空格。移除该切片集中存在的尾随字符。
参数数据类型
STRING
,STRING
返回类型
STRING
代码示例
以下是示例用例。
示例 1
以下示例将第一个参数和第二个参数传递为相同的字符串。
strings.rtrim("str", "str") = ""
示例 2
以下示例将空字符串作为第二个参数传递。
strings.rtrim("str", "") = "str"
示例 3
以下示例将空字符串作为第一个参数,将非空字符串作为第二个参数传递。
strings.rtrim("", "str") = ""
示例 4
以下示例将包含空格的字符串作为第一个参数,将非空字符串作为第二个参数传递。
strings.rtrim("a aastraa aa ", " a") = "a aasstr"
strings.to_lower
strings.to_lower(stringText)
说明
此函数接受输入字符串,并在将所有字符都更改为小写后返回字符串
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
以下示例会返回 true
。
"test@google.com" = strings.to_lower($e.network.email.to)
strings.to_upper
strings.to_upper(string_val)
说明
返回所有字母字符均为大写的原始字符串。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
以下示例会以大写形式返回所提供的参数。
strings.to_upper("example") = "EXAMPLE"
strings.trim
strings.trim(string_to_trim, cutset)
说明
从给定字符串中剪除前导和尾随空格。此外,还会从输入字符串中移除不需要的字符(由 cutset 参数指定)。
参数数据类型
STRING
,STRING
返回类型
STRING
代码示例
以下是示例用例。
示例 1
在以下示例中,将同一字符串作为输入字符串和切割集传递,这会导致生成空字符串。
strings.trim("str", "str") // ""
示例 2
在以下示例中,空字符串作为 cutset 传递,这会导致原始字符串 str,因为 cutset 中未指定要移除的字符。
strings.trim("str", "") = "str"
示例 3
在以下示例中,该函数会生成一个空字符串,因为输入字符串已为空,没有要移除的字符。
strings.trim("", "str") = ""
示例 4
在以下示例中,该函数会生成 str,因为 trim 函数会移除以下内容:
- “a aastraa aa”中的尾随空格
- 切割集中指定的字符(空格、a)
strings.trim("a aastraa aa ", " a") = "str"
strings.url_decode
strings.url_decode(url_string)
说明
给定网址字符串,解码转义字符并处理已编码的 UTF-8 字符。如果解码失败,则返回空字符串。
参数数据类型
STRING
返回类型
STRING
代码示例
示例 1
此示例展示了一个正例测试用例。
strings.url_decode("three%20nine%20four") = "three nine four"
示例 2
此示例展示了空字符串用例。
strings.url_decode("") // ""
示例 3
此示例展示了非字母字符的处理方式。
strings.url_decode("%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B") // "上海+中國"
示例 4
以下示例展示了网址解码示例。
strings.url_decode("http://www.google.com%3Fparam1%3D%22+1+%3E+2+%22%26param2%3D2%3B") // 'http://www.google.com?param1="+1+>+2+"¶m2=2;'
timestamp.as_unix_seconds
timestamp.as_unix_seconds(timestamp [, time_zone])
说明
此函数会返回一个整数,表示给定时间戳字符串自 Unix 纪元以来经过的秒数。
timestamp
是一个字符串,表示有效的从公元纪年开始的时间戳。格式需要为%F %T
。time_zone
是可选的,是表示时区的字符串。如果省略,则默认值为GMT
。您可以使用字符串字面量来指定时区。选项如下:- TZ 数据库名称,例如
America/Los_Angeles
。如需了解详情,请参阅 Wikipedia 上的 tz 数据库时区列表。 - 相对于世界协调时间 (UTC) 的时区偏离值,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
- TZ 数据库名称,例如
以下是有效 time_zone
说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
STRING
,STRING
返回类型
INT
代码示例
示例 1
有效的从公元纪年开始计算的时间戳
timestamp.as_unix_seconds("2024-02-22 10:43:00") = 1708598580
示例 2
有效的纪元时间戳(采用 America/New_York 时区)
timestamp.as_unix_seconds("2024-02-22 10:43:00", "America/New_York") = 1708616580
timestamp.current_seconds
timestamp.current_seconds()
说明
返回一个表示当前时间(以 Unix 秒为单位)的整数。大致相当于检测时间戳,并基于规则的运行时间。此函数是函数 timestamp.now()
的同义词。
参数数据类型
NONE
返回类型
INT
代码示例
示例 1
以下示例在证书过期时间超过 24 小时时会返回 true
。该示例通过减去当前的 Unix 秒数并使用大于运算符进行比较来计算时间差。
86400 < timestamp.current_seconds() - $e.network.tls.certificate.not_after
timestamp.get_date
timestamp.get_date(unix_seconds [, time_zone])
说明
此函数会返回一个格式为 YYYY-MM-DD
的字符串,表示时间戳所在的天。
unix_seconds
是一个表示经过 Unix 计时原点的秒数(例如$e.metadata.event_timestamp.seconds
)的整数,或一个包含该值的占位符。time_zone
是可选的,是表示 time_zone 的字符串。如果省略,则默认值为“GMT”。您可以使用字符串字面量来指定时区。选项包括:- TZ 数据库名称,例如“America/Los_Angeles”。如需了解详情,请参阅本页中的“TZ 数据库名称”列
- 相对于世界协调时间 (UTC) 的时区偏离值,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
以下是有效 time_zone 说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
INT
,STRING
返回类型
STRING
代码示例
示例 1
在以下示例中,省略了 time_zone
参数,因此默认值为“GMT”。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_date($ts) = "2024-02-19"
示例 2
以下示例使用字符串字面量来定义 time_zone
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_date($ts, "America/Los_Angeles") = "2024-02-20"
timestamp.get_minute
timestamp.get_minute(unix_seconds [, time_zone])
说明
此函数会返回 [0, 59]
范围内的整数,表示分钟。
unix_seconds
是一个表示经过 Unix 计时原点的秒数(例如$e.metadata.event_timestamp.seconds
)的整数,或一个包含该值的占位符。time_zone
是可选的,是表示时区的字符串。如果省略,则默认值为“GMT”。您可以使用字符串字面量来指定时区。选项包括:- TZ 数据库名称,例如“America/Los_Angeles”。如需了解详情,请参阅本页中的“TZ 数据库名称”列
- 相对于世界协调时间 (UTC) 的时区偏离值,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
以下是有效 time_zone
说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
INT
,STRING
返回类型
INT
代码示例
示例 1
在以下示例中,省略了 time_zone
参数,因此默认值为“GMT”。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_hour($ts) = 15
示例 2
以下示例使用字符串字面量来定义 time_zone
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_hour($ts, "America/Los_Angeles") = 15
timestamp.get_hour
timestamp.get_hour(unix_seconds [, time_zone])
说明
此函数会返回 [0, 23]
范围内的整数,表示小时。
unix_seconds
是一个表示经过 Unix 计时原点的秒数(例如$e.metadata.event_timestamp.seconds
)的整数,或一个包含该值的占位符。time_zone
是可选的,是表示时区的字符串。如果省略,则默认值为“GMT”。您可以使用字符串字面量来指定时区。选项包括:- TZ 数据库名称,例如“America/Los_Angeles”。如需了解详情,请参阅本页中的“TZ 数据库名称”列
- 相对于世界协调时间 (UTC) 的时区偏离值,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
以下是有效 time_zone
说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
INT
,STRING
返回类型
INT
代码示例
示例 1
在以下示例中,省略了 time_zone
参数,因此默认值为“GMT”。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_hour($ts) = 15
示例 2
以下示例使用字符串字面量来定义 time_zone
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_hour($ts, "America/Los_Angeles") = 15
timestamp.get_day_of_week
timestamp.get_day_of_week(unix_seconds [, time_zone])
说明
此函数会返回 [1, 7]
范围内的整数,表示一周中的某天(从星期日开始算起)。例如,1 = 星期日,2 = 星期一。
unix_seconds
是一个表示经过 Unix 计时原点的秒数(例如$e.metadata.event_timestamp.seconds
)的整数,或一个包含该值的占位符。time_zone
是可选的,是表示 time_zone 的字符串。如果省略,则默认值为“GMT”。您可以使用字符串字面量来指定时区。选项包括:- TZ 数据库名称,例如“America/Los_Angeles”。如需了解详情,请参阅本页中的“TZ 数据库名称”列
- 相对于世界协调时间 (UTC) 的时区偏离值,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
以下是有效 time_zone 说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
INT
,STRING
返回类型
INT
代码示例
示例 1
在以下示例中,省略了 time_zone
参数,因此默认值为“GMT”。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_day_of_week($ts) = 6
示例 2
以下示例使用字符串字面量来定义 time_zone
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_day_of_week($ts, "America/Los_Angeles") = 6
timestamp.get_timestamp
timestamp.get_timestamp(unix_seconds, optional timestamp_format, optional timezone)
说明
此函数会返回一个格式为 YYYY-MM-DD
的字符串,表示时间戳所在的天。
unix_seconds
是一个表示经过 Unix 计时原点的秒数(例如$e.metadata.event_timestamp.seconds
)的整数,或一个包含该值的占位符。timestamp_format
是可选的,是表示时间戳格式的字符串。如果省略,则默认值为%F %T
。您可以使用字符串字面量指定格式。如需了解选项,请参阅设置日期和时间部分的元素格式time_zone
是可选的,是表示时区的字符串。如果省略,则默认值为GMT
。您可以使用字符串字面量来指定时区。选项如下:- IANA 时区 (TZ) 数据库名称,例如
America/Los_Angeles
。如需了解详情,请参阅 Wikipedia 上的 tz 数据库时区列表。 - 相对于世界协调时间 (UTC) 的时区偏移量,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
- IANA 时区 (TZ) 数据库名称,例如
以下是有效 time_zone
说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
INT
、STRING
、STRING
返回类型
STRING
代码示例
示例 1
在此示例中,省略了 time_zone
参数,因此默认值为 GMT
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_timestamp($ts) = "2024-02-22 10:43:51"
示例 2
以下示例使用字符串字面量来定义 time_zone
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_timestamp($ts, "%F %T", "America/Los_Angeles") = "2024-02-22 10:43:51"
示例 3
以下示例使用字符串字面量来定义 timestamp_format
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_timestamp($ts, "%Y-%m", "GMT") = "2024-02"
timestamp.get_week
timestamp.get_week(unix_seconds [, time_zone])
说明
此函数会返回 [0, 53]
范围内的整数,表示一年中的某周。一周从星期日开始算起。一年中第一个星期日之前的日期属于第 0 周。
unix_seconds
是一个表示经过 Unix 计时原点的秒数(例如$e.metadata.event_timestamp.seconds
)的整数,或一个包含该值的占位符。time_zone
是可选的,是表示时区的字符串。如果省略,则默认值为“GMT”。您可以使用字符串字面量来指定时区。选项包括:- TZ 数据库名称,例如“America/Los_Angeles”。如需了解详情,请参阅本页中的“TZ 数据库名称”列
- 相对于世界协调时间 (UTC) 的时区偏离值,格式为
(+|-)H[H][:M[M]]
,例如“-08:00”。
以下是有效 time_zone
说明符的示例,您可以将其作为第二个参数传递给时间提取函数:
"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"
参数数据类型
INT
,STRING
返回类型
INT
代码示例
示例 1
在以下示例中,省略了 time_zone
参数,因此默认值为“GMT”。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_week($ts) = 0
示例 2
以下示例使用字符串字面量来定义 time_zone
。
$ts = $e.metadata.collected_timestamp.seconds
timestamp.get_week($ts, "America/Los_Angeles") = 0
timestamp.now
timestamp.now()
说明
返回从 1970-01-01 00:00:00 UTC 开始计算的秒数。这也称为 Unix 纪元时间。
返回类型
INT
代码示例
示例 1
以下示例会返回 2024 年 5 月 22 日 18:16:59 执行的代码的时间戳。
timestamp.now() = 1716401819 // Unix epoch time in seconds for May 22, 2024 at 18:16:59
window.avg
window.avg(numeric_values [, should_ignore_zero_values])
说明
返回输入值(可以是整数或浮点数)的平均值。将可选的第二个参数设置为 true 会忽略零值。
参数数据类型
INT|FLOAT
返回类型
FLOAT
代码示例
示例 1
此示例显示了整数平均值。
// This rule sets the outcome $size_mode to the average
// file size in the 5 minute match window.
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$size_mode = window.avg($e.file.size) // yields 2.5 if the event file size values in the match window are 1, 2, 3 and 4
示例 2
此示例显示了浮点平均值。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$size_mode = window.avg($e.file.size) // yields 1.75 if the event file size values in the match window are 1.1 and 2.4
示例 3
负输入平均值
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$size_mode = window.avg($e.file.size) // yields 0.6 if the event file size values in the match window are -1.1, 1.1, 0.0 and 2.4
示例 4
0 返回 0
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$size_mode = window.avg($e.file.size) // yields 0 if the event file size values in the match window is 0
示例 5
忽略 0 值
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$size_mode = window.avg($e.file.size, true) // yields 394 if the event file size values in the match window are 0, 0, 0 and 394
window.first
window.first(values_to_sort_by, values_to_return)
说明
此汇总函数会返回与匹配时间范围内相关性 int 值最低的事件派生的字符串值。一个示例用例是从匹配时间范围内时间戳最小的事件(最早事件)中获取用户 ID。
参数数据类型
INT
,STRING
返回类型
STRING
代码示例
获取与匹配时间范围内相关 int 值最小的事件派生的字符串值。
// This rule sets the outcome $first_event to the lowest correlated int value
// in the 5 minute match window.
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$first_event = window.first($e.metadata.timestamp.seconds, $e.metadata.event_type) // yields v1 if the events in the match window are 1, 2 and 3 and corresponding values v1, v2, and v3.
window.last
window.last(values_to_sort_by, values_to_return)
说明
此汇总函数会返回与匹配时间范围内相关性最高的整数值对应的事件派生的字符串值。示例用例是从匹配时间范围内时间戳最小的事件(时间戳最高的事件)中获取用户 ID。
参数数据类型
INT
,STRING
返回类型
STRING
代码示例
获取与匹配时间范围内相关性 int 值最高的事件派生的字符串值。
// This rule sets the outcome $last_event to the highest correlated int value
// in the 5 minute match window.
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$last_event = window.first($e.metadata.timestamp.seconds, $e.metadata.event_type) // yields v3 if the events in the match window are 1, 2 and 3 and corresponding values v1, v2, and v3.
window.median
window.median(numeric_values, should_ignore_zero_values)
说明
返回输入值的中位数。如果有 2 个中位数值,系统将非确定性地选择其中 1 个作为返回值。
参数数据类型
INT|FLOAT
,BOOL
返回类型
FLOAT
代码示例
示例 1
在输入值不为零的情况下,此示例会返回中位数。
rule median_file_size {
meta:
events:
$e.metadata.event_type = "FILE_COPY"
$userid = $e.principal.user.userid
match:
$userid over 1h
outcome:
$median_file_size = window.median($e.principal.file.size) // returns 2 if the file sizes in the match window are [1, 2, 3]
condition:
$e
}
示例 2
在输入包含一些不应忽略的零值时,此示例会返回中位数。
rule median_file_size {
meta:
events:
$e.metadata.event_type = "FILE_COPY"
$userid = $e.principal.user.userid
match:
$userid over 1h
outcome:
$median_file_size = window.median($e.principal.file.size) // returns 1 if the file sizes in the match window are [0,0, 1, 2, 3]
condition:
$e
}
示例 3
在输入包含应忽略的零值时,此示例会返回中位数。
rule median_file_size {
meta:
events:
$e.metadata.event_type = "FILE_COPY"
$userid = $e.principal.user.userid
match:
$userid over 1h
outcome:
$median_file_size = window.median($e.principal.file.size, true) // returns 2 if the file sizes in the match window are [0,0, 1, 2, 3]
condition:
$e
}
示例 4
在输入包含应忽略的所有零值的情况下,此示例会返回中位数。
rule median_file_size {
meta:
events:
$e.metadata.event_type = "FILE_COPY"
$userid = $e.principal.user.userid
match:
$userid over 1h
outcome:
$median_file_size = window.median($e.principal.file.size) // returns 0 if the file sizes in the match window are [0,0]
condition:
$e
}
示例 5
此示例表明,如果存在多个中位数,则只会返回一个中位数。
rule median_file_size {
meta:
events:
$e.metadata.event_type = "FILE_COPY"
$userid = $e.principal.user.userid
match:
$userid over 1h
outcome:
$median_file_size = window.median($e.principal.file.size) // returns 1 if the file sizes in the match window are [1, 2, 3, 4]
condition:
$e
}
window.mode
window.mode(values)
说明
返回输入值的模式。如果存在多个可能的模式值,系统将非确定性地选择其中一个值作为返回值。
参数数据类型
INT|FLOAT|STRING
返回类型
STRING
代码示例
示例 1
获取匹配窗口中值的模式。
// This rule sets the outcome $size_mode to the most frequently occurring
// file size in the 5 minute match window.
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$size_mode = window.mode($e.file.size) // yields 1.6 if the event file size values in the match window are 1.6, 2, and 1.6
window.stddev
window.stddev(numeric_values)
说明
返回匹配窗口中输入值的标准差。
参数数据类型
INT|FLOAT
返回类型
FLOAT
代码示例
示例 1
此示例会返回匹配窗口中整数的标准差。
// This rule creates a detection when the file size stddev in 5 minutes for a user is over a threshold.
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.stddev($e.file.size) // yields 4.0 if the event file size values in the match window are [10, 14, 18].
condition:
$e and #p1 > 2
示例 2
此示例会返回匹配窗口中浮点数的标准差。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.stddev($e.file.size) // yields 4.488686 if the event file size values in the match window are [10.00, 14.80, 18.97].
condition:
$e and #p1 > 2
示例 3
此示例返回包含负数的匹配窗口中的标准差。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.stddev($e.file.size) // yields 48.644972 if the event file size values in the match window are [-1, -56, -98].
condition:
$e and #p1 > 2
示例 4
在匹配期内所有值都相同的情况下,此示例会返回标准差为零。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.stddev($e.file.size) // yields 0.000000 if the event file size values in the match window are [1, 1, 1].
condition:
$e and #p1 > 2
示例 5
此示例会返回包含正数和负数的匹配窗口的标准差。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.stddev($e.file.size) // yields 1.000000 if the event file size values in the match window are [1, 0, -1].
condition:
$e and #p1 > 10
window.variance
window.variance(values)
说明
此函数会返回输入值的指定方差。
参数数据类型
INT|FLOAT
返回类型
FLOAT
代码示例
示例 1
此示例会返回所有整数的方差。
// This rule creates a detection when the file size variance in 5 minutes for a user is over a threshold.
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.variance($e.file.size) // yields 16 if the event file size values in the match window are [10, 14, 18].
condition:
$e and #p1 > 10
示例 2
此示例会返回所有浮点值的方差。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.variance($e.file.size) // yields 20.148300 if the event file size values in the match window are [10.00, 14.80, 18.97].
condition:
$e and #p1 > 10
示例 3
此示例会返回负数的方差。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.variance($e.file.size) // yields 2366.333333 if the event file size values in the match window are [-1, -56, -98].
condition:
$e and #p1 > 10
示例 4
此示例会返回一个较小的方差值。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.variance($e.file.size) // yields 0.000000 if the event file size values in the match window are [0.000000, 0.000000, 0.000100].
condition:
$e and #p1 > 10
示例 5
此示例会返回方差为零。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.variance($e.file.size) // yields 0.000000 if the event file size values in the match window are [1, 1, 1].
condition:
$e and #p1 > 10
示例 6
此示例会返回正数和负数的方差。
events:
$e.user.userid = $userid
match:
$userid over 5m
outcome:
$p1 = window.variance($e.file.size) // yields 1.000000 if the event file size values in the match window are [1, 0, -1].
condition:
$e and #p1 > 10
函数到占位符分配
您可以在 events
部分中将函数调用的结果分配给占位符。例如:
$placeholder = strings.concat($e.principal.hostname, "my-string").
然后,您可以在 match
、condition
和 outcome
部分中使用占位符变量。但是,函数到占位符的分配有两个限制:
函数到占位符分配的每个占位符都必须分配给包含事件字段的表达式。例如,以下示例有效:
$ph1 = $e.principal.hostname $ph2 = $e.src.hostname // Both $ph1 and $ph2 have been assigned to an expression containing an event field. $ph1 = strings.concat($ph2, ".com")
$ph1 = $e.network.email.from $ph2 = strings.concat($e.principal.hostname, "@gmail.com") // Both $ph1 and $ph2 have been assigned to an expression containing an event field. $ph1 = strings.to_lower($ph2)
但是,以下示例无效:
$ph1 = strings.concat($e.principal.hostname, "foo") $ph2 = strings.concat($ph1, "bar") // $ph2 has NOT been assigned to an expression containing an event field.
函数调用应依赖于一个且仅一个事件。但是,函数调用参数中可以使用来自同一事件的多个字段。例如,以下内容有效:
$ph = strings.concat($event.principal.hostname, "string2")
$ph = strings.concat($event.principal.hostname, $event.src.hostname)
但是,以下内容无效:
$ph = strings.concat("string1", "string2")
$ph = strings.concat($event.principal.hostname, $anotherEvent.src.hostname)
参考列表语法
如需详细了解引用列表行为和引用列表语法,请参阅“引用列表”页面。
您可以在 events
或 outcome
部分中使用参考列表。以下是在规则中使用各种类型的参考列表的语法:
// STRING reference list
$e.principal.hostname in %string_reference_list
// REGEX reference list
$e.principal.hostname in regex %regex_reference_list
// CIDR reference list
$e.principal.ip in cidr %cidr_reference_list
您还可以将 not
运算符和 nocase
运算符与引用列表搭配使用,如以下示例所示:
// Exclude events whose hostnames match substrings in my_regex_list.
not $e.principal.hostname in regex %my_regex_list
// Event hostnames must match at least 1 string in my_string_list (case insensitive).
$e.principal.hostname in %my_string_list nocase
nocase
运算符与 STRING
列表和 REGEX
列表兼容。
出于性能方面的原因,检测引擎会限制参考列表的使用。
- 规则中的
in
语句数上限(无论是否使用特殊运算符):7 个 - 包含
regex
运算符的in
语句数上限:4 - 包含
cidr
运算符的in
语句数上限:2
类型检查
当您在界面中创建规则时,Google Security Operations 会根据 YARA-L 语法执行类型检查。显示的类型检查错误可帮助您修改规则,以确保它按预期工作。
以下是无效谓词的示例:
// $e.target.port is of type integer which cannot be compared to a string.
$e.target.port = "80"
// "LOGIN" is not a valid event_type enum value.
$e.metadata.event_type = "LOGIN"
检测事件采样
多事件规则的检测包含事件样本,以提供有关导致检测的事件的背景信息。规则中定义的每个事件变量最多只能有 10 个事件样本。例如,如果规则定义了 2 个事件变量,则每项检测最多可以包含 20 个事件样本。此限制分别适用于每个事件变量。如果一个事件变量在此检测中包含 2 个适用事件,另一个事件变量包含 15 个适用事件,则生成的检测将包含 12 个事件样本(2 + 10)。
超出此上限的所有事件示例都会从检测中省略。
如果您想详细了解导致检测结果的事件,可以使用“结果”部分中的汇总功能,在检测结果中输出更多信息。
如果您是在界面中查看检测,则可以下载检测的所有事件示例。如需了解详情,请参阅下载事件。