YARA-L 2.0 语言语法

本部分介绍 YARA-L 语法的主要元素。另请参阅 YARA-L 2.0 语言概览

规则结构

对于 YARA-L 2.0,您必须按以下顺序指定变量声明、定义和用法:

  1. meta
  2. events
  3. match(可选)
  4. outcome(可选)
  5. condition
  6. 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
}

如需停用对零值的隐式过滤,您可以使用选项部分中的 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 属于生成的同一跳窗口时,它们才具有关联。

搜索此类事件序列的更有效方法是使用滑动窗口。当以指定的 pivot 事件变量开头或结尾时,系统会生成具有 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。

数学运算

您可以在规则的 outcomeevents 部分使用数学运算来计算整数或浮点数据类型。Google Security Operations 支持将加法、减法、乘法、除法和模数作为计算中的顶级运算符。

以下代码段是 outcome 部分中的示例计算:

outcome:
  $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))

只要每个运算数和整个算术表达式正确聚合,就允许对以下类型的运算数执行数学运算(请参阅聚合):

  • 数字事件字段
  • events 部分中定义的数字占位符变量
  • outcome 部分中定义的数字结果变量
  • 返回整数或浮点数的函数
  • 返回整数或浮点数的聚合

浮点数不允许使用模数。

结果中的占位符变量

计算结果变量时,您可以使用在规则的事件部分中定义的占位符变量。在此示例中,假设在规则的事件部分定义了 $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() 函数调用
  • 使用 anyall 修饰符

聚合

重复事件字段是非标量值。也就是说,单个变量指向多个值。例如,事件字段变量 $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 个随机元素。

当规则包含指定必须存在多个事件的 condition 部分时,聚合函数很重要,因为聚合函数会对生成检测的所有事件进行运算。

例如,如果 outcomecondition 部分包含以下内容:

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

事件和占位符条件

在此处列出事件和占位符变量的条件谓词,与关键字 andor 联接在一起。关键字 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

对不存在的要求

对于不存在要编译的规则,必须满足以下要求:

  1. 必须至少有一个 UDM 事件具有限定条件(即必须至少有一个 UDM 事件)。
  2. 如果某个占位符具有无界限条件,则必须与至少一个有界限 UDM 事件相关联。
  3. 如果某个实体具有无界限条件,则该实体必须至少与一个有界限 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 事件是有界限的,从而导致规则无法编译。

结果条件

在此处列出结果变量的条件谓词,与关键字 andor 联接,或以关键字 not 开头。

根据结果变量的类型,以不同的方式指定结果条件:

  • integer:与使用运算符 =, >, >=, <, <=, != 的整数字面量进行比较,例如:

    $risk_score > 10

  • float:与使用运算符 =, >, >=, <, <=, != 的浮点型字面量进行比较,例如:

    $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

此选项的有效值是 truefalse,用于确定是否启用此选项。默认值为 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"

默认情况下,优先级从高到低的顺序是 notandor

例如,当表达式中明确定义运算符 orand 时,“a or b and c”的求值结果为“a or (b and c)”。

events 部分,如果未明确定义运算符,则使用 and 运算符联接谓词。

如果表达式中隐含了 and 运算符,则计算顺序可能会有所不同。

例如,请考虑以下比较表达式,其中明确定义了 orand 运算符是隐式的。

$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 以忽略大小写。

  • $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) 中,某些字段被标记为重复,这表示它们是值列表或其他类型的消息。

重复字段和布尔表达式

有两种布尔表达式可用于处理重复字段:

  1. 已修改
  2. 未修改

请考虑以下事件:

event_original {
  principal {
    // ip is a repeated field
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "host"
  }
}

带修饰符的表达式

以下部分介绍了其用途以及如何在表达式中使用 anyall 修饰符。

任意

如果重复字段中的任何元素满足条件,则整个事件也满足该条件。

  • 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"

请注意,使用 anyall 编写条件时,使用 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 都不匹配,这意味着规则会检查没有与 192.168.12.16 匹配的 IP 地址。

限制:

  • anyall 运算符仅与重复字段(而非标量字段)兼容。
  • anyall 不能用于联接两个重复字段。例如,any $e1.principal.ip = $e2.principal.ip 无效。
  • 引用列表表达式不支持 anyall 运算符。

未经修改的表达式

使用未经修改的表达式时,重复字段中的每个元素都将单独处理。如果某个事件的重复字段包含 n 个元素,则系统会对该事件的 n 个副本应用规则,其中每个副本都包含重复字段的一个元素。nn这些副本是暂时的,不会被存储。

该规则会应用于以下副本:

活动文案 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" 的要求。因此,整个活动将匹配。

关于这些表达式类型的另一种理解是:

  • 使用 anyall 的重复字段的表达式作用于 event_original 中的列表。
  • 针对重复字段不使用 anyall 的表达式对各个 event_copy_n 事件进行运算。

重复的字段和占位符

重复字段适用于占位符分配。与重复字段上未经修改的表达式类似,系统会为每个元素创建一个事件副本。仍使用 event_copy 的同一示例,对于每个事件副本,占位符会获取 event_copy_n 的重复字段值的值,其中“n”是事件副本编号。n如果占位符用于匹配部分,可能会导致出现多次匹配。

以下示例生成一个匹配。对于 event_copy_1$ip 占位符等于 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 上完成。因此,您会获得三个匹配项,其中每个匹配项的 $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 个阶段。第一个阶段是事件复制:

活动文案 $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)统计在内。
  • 数组索引不能与 anyall 结合使用。例如,any $e.intermediary.ip[0] 无效。
  • 数组索引不能与映射语法结合使用。例如,$e.additional.fields[0]["key"] 无效。
  • 如果字段路径包含多个重复字段,则所有重复字段都必须使用数组索引。例如,$e.intermediary.ip[0] 是无效的,因为 intermediaryip 都是重复字段,但 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” “爱丽丝”
event_copy_2 “192.0.2.2” “爱丽丝”
event_copy_3 “192.0.2.3” “爱丽丝”
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 中。不过,引用文字的解释方式因所使用的文字而异。

  1. 双引号 (") - 用于普通字符串。必须包含转义字符。
    例如:“hello\tworld”-\t 将被解释为一个标签页

  2. 反引号 (`) - 用于按字面解释所有字符。
    例如:“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 部分中的占位符变量来指定匹配条件。

$var

使用匹配变量和占位符变量可以通过传递联接条件来声明事件字段之间的关系(请参阅事件部分语法了解更多详情)。

关键字

YARA-L 2.0 中的关键字不区分大小写。例如,andAND 是等效的。变量名称不得与关键字冲突。例如,$AND$outcome 无效。

以下是用于检测引擎规则的关键字:rulemetamatchovereventsconditionoutcomeoptionsandornotnocaseinregexcidrbeforeafterallanyanymetaifmaxmaxmatchminsumarrayarray_distinctcountcount_distinctisnull

Maps

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"]

不支持的情况

地图在下列情况下不受支持。

anyall 个关键字与地图组合

例如,系统不支持以下各项:

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 规则的以下部分:

arrays.length

支持以下语言:
arrays.length(repeatedField)

说明

返回重复字段元素的数量。

参数数据类型

LIST

返回类型

NUMBER

代码示例

示例 1

返回重复字段元素的数量。

arrays.length($e.principal.ip) = 2
示例 2

如果该路径上有多个重复字段,则返回重复字段元素的总数。

arrays.length($e.intermediary.ip) = 3

指纹

支持以下语言:
hash.fingerprint2011(byteOrString)

说明

此函数计算输入字节序列或字符串的 fingerprint2011 哈希值。此函数会返回 [2, 0xFFFFFFFFFFFFFFFF] 范围内的无符号 INT 值。

参数数据类型

BTYESTRING

返回类型

INT

代码示例

id_fingerprint = hash.fingerprint2011("user123")

群组

支持以下语言:
group(field1, field2, field3, ...)

说明

将类型相似的字段划分到一个占位符变量中。

在 UDM 搜索中,分组字段用于在多个类型相似的字段中进行搜索。分组函数与分组字段类似,只不过它允许您选择要将哪些字段组合在一起以触发检测。您可以使用组函数收集不同名词类型中有关特定实体的信息(例如主机名、IP 地址或 UserID)。

代码示例

示例 1

将所有 IP 地址归为一组,并提供扫描的时间范围内最常见 IP 地址的降序计数。

$ip = group(principal.ip, about.ip, target.ip)
$ip != ""
match:
  $ip
outcome:
  $count = count_distinct(metadata.id)
order:
  $count desc

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.log

支持以下语言:
math.log(numericExpression)

说明

返回整数或浮点表达式的自然对数值。

参数数据类型

NUMBER

返回类型

NUMBER

代码示例

示例 1
math.log($e1.network.sent_bytes) > 20

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

metrics

支持以下语言:

指标函数可以汇总大量历史数据。您可以在规则的结果部分中使用 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 地址字段。

参数数据类型

STRINGSTRING

返回类型

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。没有必要在正则表达式的开头或结尾添加 .*

Notes
  • 如需匹配确切字符串或者仅匹配前缀或后缀,请在正则表达式中添加 ^(开头)和 $(结尾)定位字符。例如,/^full$/"full" 完全匹配,而 /full/ 可以与 "fullest""lawfull""joyfully" 匹配。
  • 如果 UDM 字段包含换行符,则 regexp 仅匹配 UDM 字段的第一行。如需强制执行完整的 UDM 字段匹配,请在正则表达式中添加 (?s)。例如,将 /.*allUDM.*/ 替换为 /(?s).*allUDM.*/
  • 您可以在字符串后面使用 nocase 修饰符,以指示搜索应忽略大小写。

参数数据类型

STRINGSTRING

参数表达式类型

ANYANY

返回类型

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 个捕获组,则它将返回捕获组的第一个匹配的子字符串。定义两个或多个捕获组会返回编译器错误。

参数数据类型

STRINGSTRING

返回类型

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”。

参数数据类型

STRINGSTRINGSTRING

返回类型

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:计算结果为 BYTESTRING 的表达式。
  • 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.fromsuspicious@gmail.com 或 (2) $e.network.email.from 为空且 $e.network.email.tosuspicious@gmail.com 时,条件求值为 true。

"suspicious@gmail.com" = strings.coalesce($e.network.email.from, $e.network.email.to)
示例 2

以下示例使用两个以上的参数调用 coalesce 函数。此条件会将事件 $e 中的第一个非 null IP 地址与参考列表 ip_watchlist 中的值进行比较。参数在此调用中的合并顺序与它们在规则条件中的枚举顺序相同:

  1. 系统会先评估 $e.principal.ip
  2. 接下来评估 $e.src.ip
  3. 接下来评估 $e.target.ip
  4. 最后,如果前面的 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, ...)

说明

返回不限数量的项的串联,每个项可以是字符串、整数或浮点数。

如果任何参数是事件字段,则相应属性必须来自同一事件。

参数数据类型

STRINGFLOATINT

返回类型

STRING

代码示例

示例 1

以下示例包含字符串变量和整数变量作为参数。principal.hostnameprincipal.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”)。此外,超过十六位小数的浮点数将截断至十六位小数。

"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.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(stringText)

说明

此函数接受输入字符串,并在将所有字符更改为大写后返回一个字符串

参数数据类型

STRING

返回类型

STRING

代码示例

示例 1

以下示例返回 true

"TEST@GOOGLE.COM" = strings.to_upper($e.network.email.to)

timestamp.current_seconds

支持以下语言:
timestamp.current_seconds()

说明

返回一个表示当前时间(以 Unix 秒为单位)的整数。大致相当于检测时间戳,并基于规则的运行时间。

参数数据类型

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 是可选的,是一个表示时区的字符串。如果省略,则默认值为“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"

参数数据类型

INTSTRING

返回类型

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"

参数数据类型

INTSTRING

返回类型

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"

参数数据类型

INTSTRING

返回类型

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 是可选的,是一个表示时区的字符串。如果省略,则默认值为“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"

参数数据类型

INTSTRING

返回类型

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。如需了解详情,请参阅维基百科上的 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"

参数数据类型

INTSTRINGSTRING

返回类型

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"

参数数据类型

INTSTRING

返回类型

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

函数到占位符分配

您可以在 events 部分中将函数调用的结果分配给占位符。例如:

$placeholder = strings.concat($e.principal.hostname, "my-string").

然后,您可以在 matchconditionoutcome 部分中使用占位符变量。但是,函数到占位符的分配有两个限制:

  1. 函数到占位符分配的每个占位符都必须分配给包含事件字段的表达式。例如,以下示例有效:

    $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.
    
  2. 函数调用应依赖于一个且仅一个事件。但是,函数调用参数中可以使用来自同一事件的多个字段。例如,以下内容有效:

    $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)

引用列表语法

如需详细了解参考列表行为和参考列表语法,请参阅参考列表页面

您可以使用 eventsoutcome 部分中的参考列表。以下是在规则中使用各种类型的参考列表的语法:

// 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)。

超出此限制的任何事件样本都不会在检测中被忽略。

如果您想详细了解导致检测的事件,可以使用结果部分中的汇总功能在检测中输出更多信息。

如果您在界面中查看检测,可以下载用于检测的所有事件示例。如需了解详情,请参阅下载事件