使用统计信息分析搜索数据

支持的平台:

本页介绍了如何使用 YARA-L 2.0 对 UDM 事件运行统计查询,并对结果进行分组以供分析。

在处理环境中生成的大量 UDM 事件时,了解 UDM 搜索数据的趋势非常重要。您可以使用统计函数和聚合函数从 UDM 日志中获取可据以采取行动的数据分析。UDM 搜索支持 YARA-L 2.0 中的所有聚合函数

统计查询的使用场景

您可以在以下用例中使用统计查询:

  • 跟踪关键指标:您可以衡量 UDM 事件和关联资产(例如与已知恶意 IP 地址通信的主机)的分布和频次。

  • 检测异常行为:您可以识别可能表明存在安全事件的活动高峰,例如意外的网络流量激增或在非工作时间登录。

  • 分析随时间变化的趋势:您可以评估安全状况的变化,以评估控制措施的有效性或确定需要改进的方面,例如监控漏洞数量随时间的变化。

您可以使用类似于检测引擎规则中使用的 YARA-L 结构的语法,对 UDM 搜索查询结果进行分组和排序。如需了解详情,请参阅 使用入门:Google SecOps 中的 YARA-L 2.0

YARA-L 2.0 查询结构如下:

  • 过滤语句:指定用于过滤事件的条件。如需了解详情,请参阅过滤缺失值、零值和未初始化的值

  • 匹配(可选):定义要分组的字段。如需了解详情,请参阅匹配部分语法

  • 结果:指定查询的输出。如需了解详情,请参阅结果部分语法

  • 去重(可选):减少重复结果的数量。如需了解详情,请参阅在搜索和信息中心内使用去重功能

  • 顺序:确定查询结果的顺序,可以是 asc(升序)或 desc(降序)。如果未指定顺序(ascdesc),则默认为 asc

  • 限制(可选):设置查询返回的最大行数。

    • 示例:排序和限制使用

      以下示例展示了如何使用 order 和 limit:

      metadata.log_type = "OKTA"
      
      match:
          principal.ip
      Outcome:
          $user_count_by_ip = count(principal.user.userid)
      
      order:
      $user_count_by_ip desc
      
      limit:
          20
      

聚合函数

如果事件包含多个值,您必须使用聚合函数来汇总数据。

搜索支持以下聚合函数:

array

array 函数会以列表的形式返回所有值。它会将列表截断为最多 25 个随机元素。

语法 形参数据类型 返回值类型
array(expression) STRING LIST

代码示例

  • 返回包含事件类型的数组。

    $event_type = metadata.event_type
    outcome:
      $event_type_array = array($event_type)
    

array_distinct

array_distinct 函数以列表形式返回所有不同的值。它会将列表截断为最多 25 个随机元素。去重以获取去重后的列表是在截断之前进行的。

语法 形参数据类型 返回值类型
array_distinct(expression) STRING LIST

代码示例

  • 返回不同的事件类型

    返回包含不同事件类型的数组。

    $event_type = metadata.event_type
    outcome:
      $event_type_array = array_distinct($event_type)
    
  • 从不同的数组中排除默认值

    以下示例会过滤掉缺少安全结果说明的事件。它在重复字段上使用 any 关键字,以在结果聚合期间保留所有数组索引:

    events:
      $e.security_result[0].description != ""
      any $e.security_result.description = ""
    outcome:
      $security_result_description = array_distinct($e.security_result.description)
    

avg

avg 函数返回数值列中值的平均值。在计算过程中,系统会忽略 NULL 值。它通常与 match 结合使用,以计算数据中特定组的平均值。

语法 形参数据类型 返回值类型
avg(numericExpression) NUMBER NUMBER

代码示例

  • 查找 target.ip 不为空的所有活动。对于所有与 principal.ip 匹配的事件,将 metadata.event_timestamp.seconds 的平均值存储在一个名为 avg_seconds 的变量中。

    target.ip != ""
    match:
      principal.ip
    outcome:
      $avg_seconds = avg(metadata.event_timestamp.seconds)
    

count

count 函数用于返回组中的行数。它通常与 match 搭配使用,以获取数据中特定群组的计数。

语法 形参数据类型 返回值类型
count(expression) STRING NUMBER

代码示例

  • 返回一段时间内用户成功登录的次数。

    metadata.event_type = "USER_LOGIN"
    $security_result = security_result.action
    $security_result = "ALLOW"
    $date = timestamp.get_date(metadata.event_timestamp.seconds, "America/Los_Angeles")
    match:
        $security_result, $date
    outcome:
        $event_count = count(metadata.id)
    

count_distinct

count_distinct 函数用于返回组内具有不同值的行数。它通常与 match 结合使用,以获取数据中特定组的计数。

语法 形参数据类型 返回值类型
count_distinct(expression) STRING NUMBER

代码示例

  • 返回不同用户登录的次数

    返回不同成功用户登录的随时间变化次数。

      metadata.event_type = "USER_LOGIN"
      $security_result = security_result.action
      $security_result = "ALLOW"
      $date = timestamp.get_date(metadata.event_timestamp.seconds, "America/Los_Angeles")
      match:
          $security_result, $date
      outcome:
          $event_count = count_distinct(metadata.id)
    
  • 从去重计数中排除默认值

    以下示例会过滤掉未初始化的用户 ID,因此 count_distinct 不会将默认空字符串纳入总数:

    metadata.event_type = "USER_LOGIN"
    $userid = principal.user.userid
    $userid != ""
    match:
        metadata.event_type
    outcome:
        $distinct_users = count_distinct($userid)
    

earliest

earliest 函数会返回一组记录中最早的时间戳,精确到微秒。

语法 形参数据类型 返回值类型
earliest(timestamp) TIMESTAMP TIMESTAMP

代码示例

  • 对于所有与 hostname 匹配的事件,将最早的 metadata.event_timestamp 存储在 start 变量中。

    $hostname = principal.hostname
    match:
      $hostname
    outcome:
      $start = earliest(metadata.event_timestamp)
    

latest

latest 函数会返回一组记录中的最新时间戳,精确到微秒。

语法 形参数据类型 返回值类型
latest(timestamp) TIMESTAMP TIMESTAMP

代码示例

  • 对于所有与 hostname 匹配的事件,将 metadata.event_timestamp 的最新值存储在 end 变量中。

    $hostname = principal.hostname
    match:
      $hostname
    outcome:
      $end = latest(metadata.event_timestamp)
    

max

max 函数可返回数值列中的最大值。 它通常与 match 搭配使用,以获取数据中每个组的最大值。

语法 形参数据类型 返回值类型
max(numericExpression) NUMBER NUMBER

代码示例

  • 查找 target.ip 不为空的所有活动。对于所有与 principal.ip 匹配的事件,将 metadata.event_timestamp.seconds 的最大值存储在一个名为 max_seconds 的变量中。

    target.ip != ""
    match:
      principal.ip
    outcome:
      $max_seconds = max(metadata.event_timestamp.seconds)
    

min

min 函数可返回数值列中的最小值。它通常与 match 搭配使用,以获取数据中每个组的最小值。

语法 形参数据类型 返回值类型
min(numericExpression) NUMBER NUMBER

代码示例

  • 查找 target.ip 不为空的所有活动。对于所有与 principal.ip 匹配的事件,将 metadata.event_timestamp.seconds 的最小值存储在一个名为 min_seconds 的变量中。

    target.ip != ""
    match:
      principal.ip
    outcome:
      $min_seconds = min(metadata.event_timestamp.seconds)
    

stddev

stddev 函数返回所有可能值的标准差。

语法 形参数据类型 返回值类型
stddev(numericExpression) NUMBER NUMBER

代码示例

  • 查找 target.ip 不为空的所有活动。对于所有与 principal.ip 匹配的事件,将 metadata.event_timestamp.seconds 的标准差存储在一个名为 stddev_seconds 的变量中。

    target.ip != ""
    match:
      principal.ip
    outcome:
      $stddev_seconds = stddev(metadata.event_timestamp.seconds)
    

sum

sum 函数返回数值列中值的总和。在计算过程中,它会忽略 NULL 值。它通常与 match 结合使用,以计算数据中不同组的总和。

语法 形参数据类型 返回值类型
sum(numericExpression) NUMBER NUMBER

代码示例

  • 查找 target.ip 不为空的所有活动。对于所有与 principal.ip 匹配的事件,将 network.sent_bytes 的总和存储在一个名为 sent_bytes 的变量中。

    target.ip != ""
    match:
      principal.ip
    outcome:
      $sent_bytes = sum(network.sent_bytes)
    

过滤缺失值、零值和未初始化的值

汇总统一数据模型 (UDM) 事件数据时,结果中可能会包含意外的空字符串、零值或 [Unknown] 条目。这是因为 YARA-L 2.0 将未初始化的字段评估为默认零值,而不是 NULL

例如,未初始化的字符串字段默认为空字符串 (""),整数字段默认为零 (0),枚举字段默认为其未指定的值(例如 principal.security_result.action"UNKNOWN_ACTION")。使用零值可防止负比较过滤器(例如 $e.principal.hostname != "test_domain")意外排除缺少主机名的事件。

由于聚合函数会将默认零值视为有效数据,因此这种行为会以以下方式影响查询结果:

  • 去重后的数量count_distinct 等函数会将默认零值视为唯一项。如果某些事件中缺少某个字段,count_distinct 会将默认零值视为一个额外的项,从而使总计数增加 1。
  • 数组列表arrayarray_distinct 等函数会在返回的列表中包含默认零值。如果结果数组仅包含空字符串 ([""]),则检测时间轴会将该值显示为 [Unknown]

如需从汇总中移除默认值,请在查询的 events 部分中添加过滤条件以排除这些值(例如 $e.field != ""$e.field != 0$e.field != "UNKNOWN_ACTION")。

过滤重复字段时,请在过滤条件前面加上 any 关键字,例如 any $e.security_result.description != ""。使用 any 会在整个事件中评估条件,同时在结果汇总数据时保留所有数组索引。

YARA-L 2.0:搜索与 UDM 的比较

  • 用于搜索活动窗口的 over 关键字在搜索中不受支持。

  • UDM 搜索查询不包含 conditionoption 部分。

如需详细比较 UDM 搜索查询和实时 YARA-L 2.0 检测规则,请参阅 UDM 搜索与规则结果的比较

按时间粒度分组

您可以按指定的时间粒度对 match 部分中的事件字段和占位变量进行分组,类似于在 SQL 中对列进行分组。

语法如下:

  • 语法格式

    match:
      ... [BY|OVER EVERY] [FIRST] [NUMBER] [TIME_GRANULARITY]
    

如需按时间粒度进行分组,您可以使用关键字 byover every。允许的时间粒度如下:

  • MINUTEm
  • HOURh
  • DAYd
  • WEEKw
  • MONTHmo

byover every 关键字在功能上是等效的。您可以将一个叠加在另一个之上。

  • 示例:每两小时按 IP 地址和主机名分组

    $hostname = principal.hostname
    match:
      $hostname, target.ip by 2h
    
  • 示例:按主机名分组,时间粒度为全天

    $hostname = principal.hostname
    match:
      $hostname by minute
    
  • 示例:按主机名和事件发生日期对所有事件进行分组

    $hostname = target.hostname
    match:
      $hostname over every day
    outcome:
      $events_count = count($hostname)
    

按时间范围对数据源进行分组

某些数据源(例如实体上下文)在时间范围 (<start_time>, <end_time>) 内有效,而不是在单个时间戳内有效。按这些数据源的时间粒度进行分组时,您可以评估整个时间范围,也可以将分组限制为开始时间戳。

评估整个时间范围(默认)

默认情况下,如果您省略 first 关键字,查询会评估记录的整个时间范围。

  • 示例:按实体 IP 地址在整个时间范围内进行分组

    graph.entity.hostname != ""
    match:
      graph.entity.ip by hour
    outcome:
      $min_seconds = min(graph.metadata.event_metadata.event_timestamp.seconds)
    

使用第一个关键字评估开始时间戳

如需将分组限制为仅针对记录的开始时间戳 (<start_time>),请在 match 语句中添加可选的 first 关键字。您可以将 firstbyover every 搭配使用(by first 等同于 over every first)。

例如,假设某个实体的时间范围为 1m5m,时间粒度为 1m。如果使用 first 按主机 (h1, h2) 对结果进行分组,则返回的列将为 (h1, 1m) 和 (h2, 1m),其余时间范围将被忽略。

  • 示例:仅使用开始时间按实体 IP 地址分组

    graph.entity.hostname != ""
    match:
      graph.entity.ip by first hour
    outcome:
      $min_seconds = min(graph.metadata.event_metadata.event_timestamp.seconds)
    

在搜索中创建并保存可视化图表

本部分概述了 Google SecOps 统一数据模型 (UDM) 搜索中的数据可视化功能。借助此功能,安全运维中心 (SOC) 分析师可以根据搜索结果创建可视化图表并将其保存到信息中心,从而高效地检测、调查和应对威胁。

如需创建可视化图表,您需要拥有 chronicle.nativeDashboards.createchronicle.nativeDashboards.update IAM 权限。

创建并保存可视化图表以添加到信息中心

如需创建并保存可视化图表以添加到信息中心,请执行以下操作:

  1. 编写包含 matchoutcome 部分的 YARA-L 查询。

  2. 选择日期范围,然后点击运行搜索以运行查询。 在统计信息可视化图表标签页中查看结果。

  3. 可视化标签页中,执行以下操作: a. 从图表类型列表中选择图表类型。 b. 调整数据设置下的设置,以自定义图表。

  4. 添加到信息中心界面上,执行以下操作: a. 输入图表名称说明时间范围。 b. 选择将图表添加到现有信息中心,或创建新信息中心。

  5. 点击添加到信息中心,将图表添加到信息中心。

限制

以下限制适用于统计查询执行:

  • 查询无法处理存在时间超过 90 天的数据(3 个月的回溯期)。
  • 统计查询最多返回 10,000 个结果。

需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。