你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

开发高级安全信息模型 (ASIM) 分析程序

高级安全信息模型 (ASIM) 用户在查询中使用 统一分析程序 而不是表名,以规范化格式查看数据,并在查询中包含与架构相关的所有数据。 统一分析器反过来使用 特定于源分析程序 来处理每个源的特定详细信息。

Microsoft Sentinel 为许多数据源提供内置的特定于源的分析程序。 在下列情况下,可能需要修改或开发这些特定于源的分析程序:

  • 当你的设备提供符合 ASIM 架构的事件,但 Microsoft Sentinel 中没有适用于你的设备及相关架构的源专用分析器时。

  • 当你的设备有可用的 ASIM 源特定分析程序,但设备发送事件的方法或格式与 ASIM 分析程序预期的不同。 例如:

    • 源设备可能配置为以非标准方式发送事件。

    • 你的设备的版本可能不同于 ASIM 分析程序支持的版本。

    • 中间系统可能会收集、修改和转发这些事件。

若要了解分析器如何适应 ASIM 体系结构,请参阅 ASIM 体系结构图

自定义 ASIM 分析器开发过程

以下工作流介绍了开发自定义 ASIM 特定源解析器的主要步骤:

  1. 收集示例日志

  2. 确定从源发送的事件所代表的架构或架构。 有关详细信息,请参阅架构概述

  3. 将源事件字段映射到已标识的架构。

  4. 为源开发一个或多个 ASIM 分析程序。 需要针对与源相关的每个架构开发筛选分析器和无参数分析程序。

  5. 测试解析器。

  6. 将分析程序部署到 Microsoft Sentinel 工作区。

  7. 更新相关的 ASIM 统一分析程序以引用新的自定义分析程序。 有关详细信息,请参阅管理 ASIM 分析程序

  8. 你可能还想向主要的 ASIM 发行版贡献你的解析器。 贡献者提供的解析器也可以作为内置解析器在所有工作区中提供。

本文将指导你完成过程的开发、测试和部署步骤。

收集示例日志

若要构建有效的 ASIM 分析程序,需要一组具有代表性的日志,因此在大多数情况下需要设置源系统并将其连接到 Microsoft Sentinel。 如果没有可用的源设备,云即用即付服务允许你部署许多设备进行开发和测试。

此外,查找供应商文档和日志示例有助于加快开发速度,并通过确保广泛的日志格式覆盖面来减少错误。

一组具有代表性的日志应包括:

  • 具有不同事件结果的事件。
  • 具有不同响应操作的事件。
  • 用户名、主机名和 ID 以及需要值规范化的其他字段的不同格式。

Tip

使用同一架构的现有解析器创建新的自定义解析器。 使用现有分析程序对于筛选分析程序以确保它们接受架构所需的所有参数尤其重要。

规划映射

在开发分析程序之前,请将源事件中可用的信息映射到你已标识的架构:

  • 映射所有必填字段,最好也映射建议字段。
  • 尝试将源中的任何可用信息映射到规范化字段。 如果不作为所选架构的一部分提供,请考虑映射到其他架构中可用的字段。
  • 将源中的字段值映射到 ASIM 允许的规范化值。 原始值存储在单独的字段中,例如 EventOriginalResultDetails

开发分析程序

为每个相关架构开发筛选和无参数分析程序。

自定义解析器是在 Microsoft Sentinel 日志页中创建的 KQL 查询。 分析器查询包含三个部分:

筛选>解析>准备字段

将解析器操作保持在记录级别

分别对每个源记录进行规范化。 一个源记录在过滤后可以生成零记录,也可以产生一条归一化记录。

  • 只从声明的源表读取事件记录。 不要通过第二次表读取、事件记录 join、工作区表或监视列表引用、externaldata 或其他外部表格源来执行同表或跨表事件扩充。
  • 保持记录数量不变。 不要把一个源记录变成多个归一化记录。 如果源将多个逻辑事件合并在一条记录中,请纠正连接器或源事件格式。
  • 不要使用任何 mv-* 算符,包括 mv-expandmv-apply
  • 不要将事件记录与 summarizedistinctarg_minarg_max、 或等效操作关联、去重、聚合或重聚合。

当每个查找键都是唯一的时,允许使用 datatable 创建并使用 lookup 应用的查询本地静态映射。 使用标量表达式,直接访问动态值和当前行可用的值。 如果字段无法在没有禁止模式的情况下映射,则纠正连接器或源事件形状,或者保持非强制字段不映射。

筛选

筛选相关记录

在许多情况下,Microsoft Sentinel 中的表包含多个事件类型。 例如:

  • Syslog 表包含来自多个源的数据。
  • 自定义表可以包含来自单个源的信息,该源提供多种事件类型并可适应各种架构。

因此,分析程序应首先仅筛选与目标架构相关的记录。

在 KQL 中,筛选是使用 where 运算符完成的。 例如,Sysmon 事件 1 报告进程创建,因此规范化为 ProcessEvent 架构。 Sysmon 事件 1 属于 Event 表,因此你可以使用以下查询仅筛选 Sysmon 进程创建事件:

Event | where Source == "Microsoft-Windows-Sysmon" and EventID == 1

Important

分析程序不应按时间进行筛选。 使用分析程序的查询将应用时间范围。

按源字段筛选

在当前事件中使用物理字段来识别源类型。 不要查询监控列表或其他表格来识别相关记录。

如果事件信息不足以区分源或事件类型,请更新连接器以包含源标识符,或将事件路由到特定源的表。 不要通过扩充表格内容来弥补源信息缺失。

基于分析程序参数进行筛选

开发筛选分析程序时,请确保分析程序接受相关架构的筛选参数,如该架构的参考文章中所述。 使用现有分析程序作为起点可确保分析程序包含正确的函数签名。 在大多数情况下,对于同一架构的筛选分析程序,实际筛选代码也类似。

筛选时,请确保:

  • 在使用物理字段分析之前进行筛选。 如果筛选后的结果不够准确,请在分析后重复该测试以微调结果。 有关更多信息,请参阅筛选优化
  • 如果参数未定义且仍具有默认值,则不进行筛选

使用条件谓词实现可选的解析器参数过滤,使解析器仅在调用者提供值时应用过滤。 以下示例显示了如何对字符串参数(默认值通常为“*”)和列表参数(默认值通常为空列表)实现筛选。

srcipaddr=='*' or ClientIP==srcipaddr
array_length(domain_has_any) == 0 or Name has_any (domain_has_any)

有关该 array_length 函数和操作符 has_any 的更多信息,请参见Kusto文档:

筛选优化

为了确保分析器保持良好的性能,请注意以下筛选建议:

  • 始终对内置字段进行筛选,而不是对解析后的字段进行筛选。 尽管有时使用已分析的字段进行筛选更简单,但这会显著影响性能。
  • 使用有利于优化性能的运算符。 特别是 ==hasstartswith。 使用 containsmatches regex 之类的运算符也会对性能造成很大的影响。

性能筛选建议可能并不总是容易遵循。 例如, 使用 has 的准确度不如 contains。 在其他情况下,匹配内置字段(例如 SyslogMessage)不如比较提取的字段(例如 DvcAction)那么准确。 在这种情况下,我们建议你仍使用性能优化运算符对内置字段进行预筛选,并在分析后使用更准确的条件重复筛选。

有关示例,请参阅以下 Infoblox DNS 分析程序代码片段。 该分析器首先检查 SyslogMessage 字段是否 has(包含)单词 client。 但是,术语可能在消息中的不同位置使用,因此在分析 Log_Type 字段后,分析程序会再次检查单词 client 是否确实是字段的值。

Syslog | where ProcessName == "named" and SyslogMessage has "client"
…
      | extend Log_Type = tostring(Parser[1]),
      | where Log_Type == "client"

注释

分析程序不应按时间筛选数据,因为使用分析程序的查询已针对时间进行筛选。

分析

查询选择相关的记录后,可能需要分析这些记录。 通常,如果在一个文本字段中传达多个事件字段,则需要进行分析。

下面按性能优化顺序列出了执行分析的 KQL 运算符。 第一个具有最优的性能,而最后一个的性能优化程度最低。

运算符/函数() Description
split() 函数 分析带分隔值的字符串。
parse_csv () 函数 分析 CSV(逗号分隔值)行格式的值的字符串。
parse-kv 运算符 从字符串表达式中提取结构化信息,并以键/值形式表示该信息。
parse 运算符 使用模式分析任意字符串中的多个值,该模式可以是性能更佳的简化模式,也可以是正则表达式。
extract_all() 函数 使用正则表达式分析任意字符串中的单一值。 extract_all 的性能类似于 parse(如果后者使用正则表达式)。
extract() 函数 使用正则表达式从任意字符串中提取单个值。

如果需要单个值,则使用 extract 的性能比使用 parseextract_all 更好。 但是,对同一源字符串多次激活 extract 则不如单次激活 parseextract_all 高效,因此应避免此操作。
parse_json () 函数 分析格式为 JSON 的字符串中的值。 如果只需要 JSON 中的少量几个值,则使用 parseextractextract_all 可提供更好的性能。
parse_xml() 函数 分析格式为 XML 的字符串中的值。 如果只需要 XML 中的几个值,则使用 parseextractextract_all 提供更好的性能。

规范化

字段名称映射

最简单的规范化形式是将原始字段重命名为其规范化名称。 为此,请使用 运算符 project-rename 。 使用项目重命名可确保该字段仍作为物理字段进行管理,并且处理该字段时的性能更高。 例如,以下查询将源帐户字段映射到其规范化后的 ASIM 执行者字段名称:

 | project-rename
    ActorUserId = InitiatingProcessAccountSid,
    ActorUserAadId = InitiatingProcessAccountObjectId,
    ActorUserUpn = InitiatingProcessAccountUpn,

规范化字段格式和类型

在许多情况下,需要对提取出的原始值进行规范化处理。 例如,在 ASIM 中,MAC 地址使用冒号作为分隔符,而源可能会发送以连字符分隔的 MAC 地址。 用于转换值的主要运算符是 extend,还有一组广泛的 KQL 字符串、数字和日期函数也可用于转换值。

此外,确保分析程序输出字段与架构中定义的类型匹配,这对于分析程序正常工作至关重要。 例如,可能需要将表示日期和时间的字符串转换为 datetime 字段。 在这种情况下,todatetimetohex 等函数非常有用。

例如,原始唯一事件 ID 可能以整数的形式发送,但 ASIM 要求该值为字符串以确保数据源之间的广泛兼容性。 因此,在赋值源字段时,应将数值转换为字符串,使用extendtostring和代替project-rename,以便规范化字段符合模式字符串类型要求:

  | extend EventOriginalUid = tostring(ReportId),

派生字段和值

源字段的值一旦提取出来,可能需要映射到目标模式字段指定的值集合。 使用标量表达式如 iffcase,或带有 lookup的查询本地静态datatable表达式,将可用数据映射到目标值。

例如,Microsoft DNS 解析器从源特定事件和响应代码推导出归一化的成功或失败结果。 解析器根据事件 ID 和响应代码,使用如下iff语句为EventResult字段赋值:

   extend EventResult = iff(EventId==257 and ResponseCode==0 ,'Success','Failure')

当源值可以映射到多个归一化值时,就使用 case 。 例如:

| extend NetworkProtocol = case(
    Proto == 6, "TCP",
    Proto == 17, "UDP",
    ""
)

对于较大的静态映射,请定义一个查询局部维度表,并使用 lookup 应用它。 查找右侧必须是本地定义的静态 datatable,而不是工作区表、监视列表或外部数据源。 每个查找键只定义一行,这样一个源记录就不能产生多个归一化记录。 例如:

let NetworkProtocolLookup = datatable(Proto:real, NetworkProtocol:string)
[
    6, "TCP",
    17, "UDP"
];
...
| lookup NetworkProtocolLookup on Proto

扩充字段

除了源中可用的字段外,生成的 ASIM 事件还包括分析程序应生成的扩充字段。 这些模式字段使用当前行或常量的值,不需要表的丰富化。 在许多情况下,解析器可以为这些字段分配一个常数值。 填充标准丰富字段,使每个解析记录包含一致的产品、供应商和模式元数据,例如:

  | extend                  
     EventCount = int(1),
     EventProduct = 'M365 Defender for Endpoint',
     EventVendor = 'Microsoft',
     EventSchemaVersion = '0.1.0',
     EventSchema = 'ProcessEvent'

分析程序应设置的另一种类型的扩充字段是类型字段,它们指定存储在相关字段中的值的类型。 例如,SrcUsernameType 字段指定 SrcUsername 字段中存储的值类型。 可以在实体说明中找到有关类型字段的详细信息。

在大多数情况下,还会为类型分配一个常量值。 然而,在某些情况下,类型必须根据实际价值来确定。 例如,通过检查解析后的主机名是否包含多个段来判断是否为完全限定域名(FQDN):

   DomainType = iif (array_length(SplitHostname) > 1, 'FQDN', '')

Microsoft Sentinel 提供用于处理扩充的有用函数。 例如,使用 _ASIM_ResolveSrcFQDN 辅助函数从列中推导出归一化的源主机名、域、域类型和FQDN字段 Computer 。 以下代码片段会根据 Computer 字段中的值,自动填充 SrcHostnameSrcDomainSrcDomainTypeSrcFQDN 字段。

  | invoke _ASIM_ResolveSrcFQDN('Computer')

此函数将按如下所示设置字段:

计算机领域 输出字段
server1 SrcHostname: server1
SrcDomain、SrcDomainType、SrcFQDN 全部为空
server1.microsoft.com SrcHostname: server1
SrcDomain:microsoft.com
SrcDomainType: FQDN
SrcFQDN:server1.microsoft.com

函数 _ASIM_ResolveDstFQDN_ASIM_ResolveDvcFQDN 执行填充相关 DstDvc 字段的类似任务。 有关 ASIM 帮助函数的完整列表,请参阅 ASIM 函数

在结果集中选择字段

解析器可以选择性地从结果集中选取字段。 删除不需要的字段可避免规范化字段和剩余源字段之间的混淆,从而提高性能并提高清晰度。

以下 KQL 运算符用于在结果集中选择字段:

Operator Description 何时在分析器中使用
project-away 删除字段。 对于要从结果集中删除的特定字段,请使用 project-away。 建议不要从结果集中删除未规范化的原始字段,除非它们会造成混淆或非常大,并且可能会影响性能。
项目 选择之前存在或作为语句的一部分创建的字段,并删除所有其他字段。 不建议在分析器中使用,因为分析器不应删除未规范化的任何其他字段。

如果需要删除特定字段(例如分析期间使用的临时值),请使用 project-away 从结果中删除它们。

例如,在解析自定义日志表时,移除剩余的源特定类型列(如带有 _d_s_b_g 后缀的字段),使解析器输出只包含你打算保留的归一化字段:

    | project-away
        *_d, *_s, *_b, *_g

处理解析变体

Important

为代表不同事件类型或映射到不同模式的变体开发独立解析器。

如果同一事件类型的不同变体需要不同的解析逻辑,可以使用标量条件表达式(例如 iffcase),同时仍为每条源记录保留一条输出记录。 不要创建表格式分支并使用 union 将其重新合并,因为分支可能会多次处理或返回同一条源记录。

部署解析器

通过将分析程序复制到 Azure Monitor 日志页面并将查询保存为函数来手动部署分析程序。 此方法可用于测试。 有关详细信息,请参阅创建函数

若要部署大量分析程序,建议使用分析程序 ARM 模板,如下所示:

  1. 请根据每个模式的相关模板创建一个 YAML 文件,并将你的查询包含在其中。 从与架构和分析程序类型、筛选或无参数相关的 YAML 模板 开始。

  2. 使用 ASIM YAML 到 ARM 模板转换器,将 YAML 文件转换为 ARM 模板。

  3. 如果部署更新,请使用门户或PowerShell 函数删除工具删除旧版本的函数。

  4. 使用 Azure 门户PowerShell 部署模板。

还可使用关联模板将多个模板合并到单个部署过程

Tip

ARM 模板可以组合不同资源,因此解析器可以与连接器、分析规则或监视列表一起部署。 保持解析器与监控列表和其他表的独立。

测试解析器

ASIM提供了测试工具,你可以用来验证自定义解析器。 尽管如此,解析器也是代码,有时很复杂,因此除了自动化测试之外,还推荐使用标准的质量保证实践,如代码审查。

安装 ASIM 测试工具

在部署ASIM测试工具之前,请确保你有一个Microsoft Sentinel工作空间,具备以下功能:

  • 你的解析器已部署。
  • 分析程序使用的源表可用。
  • 解析器使用的源表充满了一系列各种相关事件。

当你的工作区满足这些要求时,将 ASIM测试工具部署 到该工作区。

验证输出架构

为了确保解析器生成的模式有效,请在 Microsoft Sentinel 日志页面运行以下模式测试查询。 该命令验证解析器的输出字段、类型和别名是否符合预期的ASIM模式:

<parser name> | getschema | invoke ASimSchemaTester('<schema>')

按如下所示处理结果:

错误 Action
缺少必填字段 [<Field>] 将该字段添加到解析器中。 在许多情况下,这将是派生值或常量值,而不是源中已有的字段。
当必填列 [<Field>] 存在时,缺少的字段 [<Field>] 是必填的 将该字段添加到解析器中。 在许多情况下,此字段表示它引用的现有列的类型。
当列 [<Field>] 存在时,缺少的字段 [<Field>] 是必填的 将该字段添加到解析器中。 在许多情况下,此字段表示它引用的现有列的类型。
缺少为现有列 [<Field>] 指定别名的强制别名 [<Field>] 将该别名添加到解析器中。
缺少为现有列 [<Field>] 指定别名的建议别名 [<Field>] 将该别名添加到解析器中。
缺少为现有列 [<Field>] 指定别名的可选别名 [<Field>] 将该别名添加到解析器中。
缺少用于为缺失列 [<Field>] 起别名的必填别名 [<Field>] 此错误附带别名字段的类似错误。 更正别名字段错误,并将此别名添加到分析程序。
字段 [<Field>] 的类型不匹配。 它当前为 [<Type>] ,应为 [<Type>] 请确保规范化字段的类型是正确的,通常的方法是使用转换函数,例如 tostring
信息 Action
缺少推荐的字段 [<Field>] 请考虑将此字段添加到分析程序。
信息 Action
缺少用于为不存在的列 [<Field>] 起别名的建议别名 [<Field>] 如果将别名字段添加到分析程序,请确保也添加此别名。
缺少可选别名 [<Field>],该别名指向不存在的列 [<Field>] 如果将别名字段添加到分析程序,请确保也添加此别名。
缺少可选字段 [<Field>] 虽然可选字段通常缺失,但值得查看列表以确定是否可以从源映射任何可选字段。
额外的未规范化字段 [<Field>] 尽管未规范化的字段有效,但值得查看列表以确定任何未规范化的值是否可映射到可选字段。

注释

错误将阻止使用分析程序的内容正常工作。 警告不会阻止内容正常工作,但可能会降低结果的质量。

验证输出值

为了确保解析器产生有效值,使用ASIM数据测试器验证解析器输出样本的字段值,并识别任何错误或警告。 在 Microsoft Sentinel 日志页面运行以下查询:

<parser name> | limit <X> | invoke ASimDataTester ('<schema>')

指定架构是可选的。 如果未指定架构,则 EventSchema 字段用于标识事件应遵循的架构。 如果事件不包含 EventSchema 字段,则只会验证公用字段。 如果将架构指定为参数,则此架构将用于测试所有记录。 这对于未设置 EventSchema 字段的较旧分析程序非常有用。

注释

即使未指定架构,函数名称后也需要空括号。

此测试占用大量资源,可能无法用于整个数据集。 将 X 设置为查询不会超时的最大数字,或者使用时间范围选取器设置查询的时间范围。

按如下所示处理结果:

消息 Action
(0) 错误:列 [<Field>] 的类型不匹配。 它当前为 [<Type>] ,应为 [<Type>] 请确保规范化字段的类型是正确的,通常的方法是使用转换函数,例如 tostring
(0) 错误:类型为 [<逻辑类型>] 的字段 [<字段>] 存在无效值(最多列出 10 个) 请确保分析程序将正确的源字段映射到输出字段。 如果映射正确,请更新分析程序,将源值转换为正确的类型、值或格式。 请参阅逻辑类型列表,详细了解每个逻辑类型的正确值和格式。

请注意,测试工具仅列出了 10 个无效值的示例。
(1) 警告: 必填字段 [<Field>] 中存在空值 应填充必填字段,而不只是定义必填字段。 检查对于当前来源为空的记录,是否可以从其他来源填充该字段。
(2) 信息: 建议的字段 [<Field>] 中存在空值 建议的字段通常应填充。 检查对于当前来源为空的记录,是否可以从其他来源填充该字段。
(2) 信息: 可选字段 [<Field>] 中存在空值 检查别名字段是必需还是建议的,如果是,是否可以从其他源填充该字段。

许多消息还会报告生成消息的记录数及其占样本总数的百分比。 此百分比很好地表明问题的重要性。 例如,对于推荐字段:

  • 90% 的空值可能表示存在一般分析问题。
  • 25% 的空值可能指示未正确分析的事件变体。
  • 少量空值可能是一个微不足道的问题。

注释

错误将阻止使用分析程序的内容正常工作。 警告不会阻止内容正常工作,但可能会降低结果的质量。

贡献解析器

你可能希望将该分析器贡献给 ASIM 主发行版。 如果分析程序被接受,它们将作为 ASIM 内置分析程序提供给每个客户。

若要贡献您的解析器,请执行以下操作:

记录已接受的警告

如果ASIM测试工具列出的警告被认为对解析器有效,请使用例外部分在解析器YAML文件中记录被接受的警告。 以下 YAML 示例展示了如何在解析器定义部分记录被接受的 Exceptions 解析器测试警告:

Exceptions:
- Field: DnsQuery 
  Warning: Invalid value
  Exception: May have values such as "1164-ms-7.1440-9fdc2aab.3b2bd806-978e-11ec-8bb3-aad815b5cd42" which are not valid domains names. Those are related to TKEY RR requests.
- Field: DnsQuery
  Warning: Empty value in mandatory field
  Exception: May be empty for requests for root servers and for requests for RR type DNSKEY

YAML 文件中指定的警告应是对应的 ASIM 测试器警告消息的简短形式,且足够独特以识别该特定警告。 该值用于在自动测试中匹配ASIM测试员的警告信息,并忽略匹配的警告。

示例提交指南

在排查分析程序问题并确保分析程序的未来更新符合旧示例时,需要使用示例数据。 提交的示例应包括分析程序支持的任何事件变体。 请确保示例事件包括所有可能的事件类型、事件格式和变体,例如表示成功和失败活动的事件。 此外,请确保不同的值格式变化得到体现。 例如,如果主机名可以表示为 FQDN 或简单主机名,则示例事件应同时包含这两种格式。

若要提交事件示例,请使用以下步骤:

  • Logs 屏幕中,运行一个查询,以仅从源表中提取分析程序选择的事件。 例如,对于 Infoblox的DNS解析器,使用以下查询只检索解析器处理的Infoblox NIOS Syslog记录:
    Syslog
    | where ProcessName == "named"
  • 使用“导出到 CSV”选项将结果导出到名为 <EventVendor>_<EventProduct>_<EventSchema>_IngestedLogs.csv 的文件,其中 EventProductEventProductEventSchema 是分析程序分配给这些字段的值。

  • Logs 屏幕上,运行 getschema 源表以检查可用的列及其类型。 将这些模式信息与样本数据一同导出。 例如,对于Infoblox的DNS解析器,查询为:

    Syslog
    | getschema
  • 使用“导出到 CSV”选项将结果导出到名为 <TableName>_schema.csv 的文件,其中 TableName 是分析程序使用的源表的名称。

  • 在文件夹 /Sample Data/ASIM 中将这两个文件都包含在 PR 中。 如果文件已存在,则将 GitHub 用户名添加到名称,例如:<EventVendor>_<EventProduct>_<EventSchema>_SchemaTest_<GitHubHandle>.csv

测试结果提交指南

测试结果对于验证分析程序的正确性并了解报告的任何异常非常重要。

若要提交测试结果,请使用以下步骤:

  • 按照 测试解析器中描述的操作进行分析测试。

  • 并使用“导出到 CSV”选项将测试结果导出到分别名为 <EventVendor>_<EventProduct>_<EventSchema>_SchemaTest.csv<EventVendor>_<EventProduct>_<EventSchema>_DataTest.csv 的文件。

  • 在文件夹 /Parsers/ASim<schema>/Tests 中将这两个文件都包含在 PR 中。

了解有关 ASIM 分析程序的更多信息:

详细了解 ASIM 的一般信息: