前言
Wazuh 是一个开源的安全平台,它使用解码器(decoders)来从接收到的日志消息中提取信息。解码器将日志信息分割成字段,以便进行分析。Wazuh解码器使用XML语法,允许用户指定日志数据应该如何被解析和规范化。解码器的工作分为两个阶段:预解码(pre-decoding)和解码(decoding)。在预解码阶段,如果存在类似 syslog 的头部,会提取时间戳、主机名和程序名等一般信息。在随后的解码阶段,解码器解析并解释剩余的日志数据,提取更多相关信息。
文章目录
- 前言
- 1 解码器
- 1.1 运行示例
- 1.2 规则格式
- 1.2.1 decoder
- 1.2.2 parent
- 1.2.3 accumulate
- 1.2.4 program_name
- 1.2.5 prematch
- 1.2.6 regex
- 1.2.7 order
- 1.2.8 fts
- 1.2.9 ftscomment
- 1.2.10 plugin_decoder
- 1.2.11 use_own_name
- 1.2.12 json_null_field
- 1.2.12 json_array_structure
- 1.2.13 var
- 1.2.14 type
- 1.3 JSON解码器
- 1.4 解码器之间的关系
- 1.4.1 父子解码器
- 1.4.2 兄弟解码器
- 1.4.3 解码器间如何建立关系
- 1.5 自定义解码器
- 1.5.1 新增解码器
- 1.5.2 修改内置解码器
1 解码器
1.1 运行示例
wazuh-logtest是Wazuh安全平台中的一个工具,它允许用使用日志样本进行测试和验证。这个工具对于编写和调试自定义规则和解码器、排查误报和漏报非常有用。该工具位于/var/ossec/bin/wazuh-logtest路径下。
下面是示例日志:
Apr 14 19:28:21 gorilla sshd[31274]: Connection closed by 192.168.1.33
启动wazuh-logtest工具,并将上面日志粘贴到终端后按回车执行,该工具输出结果如下:
Type one log per line
Apr 14 19:28:21 gorilla sshd[31274]: Connection closed by 192.168.1.33
**Phase 1: Completed pre-decoding.
full event: 'Apr 14 19:28:21 gorilla sshd[31274]: Connection closed by 192.168.1.33'
timestamp: 'Apr 14 19:28:21'
hostname: 'gorilla'
program_name: 'sshd'
**Phase 2: Completed decoding.
name: 'sshd'
parent: 'sshd'
srcip: '192.168.1.33'
通过分析上述输出,我们可以了解到日志解码过程包含两个主要步骤:预解码和解码。在预解码步骤中,解码器会识别并提取类似Syslog头部的元素,例如时间戳、主机名和程序名称。进入解码阶段后,它将进一步提取日志正文中的关键数据。以上述示例为例,解码阶段成功识别出了源IP地址为192.168.1.33。
1.2 规则格式
Wazuh解码器采用XML语言进行配置,使得用户能够定义日志数据的解析和规范化方式。在Wazuh的安装目录中,/var/ossec/ruleset/decoders路径下存放了众多预设的解码器规则。以下是一些关键的解码器配置选项的简要说明:
1.2.1 decoder
decoder用作解码器文件的根元素。它封装了解码器的定义,包括其名称、类型以及指示它如何处理日志消息和从日志消息中提取信息的特定属性。该标签支持的属性如下表所示:
属性 | 描述 |
---|---|
name | 标识解码器的名称 |
下面是该标签使用示例,示例中<decode>和</decoder>定义了一个名字叫json_custom_decoder的解码器。
<decoder name="json_custom_decoder">
<type>json</type>
<program_name>application_logs</program_name>
<regex>"message": "(.*?)"</regex>
<order>message_content</order>
<plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>
1.2.2 parent
指定当前解码器的父解码器名称。父解码器可以有多个子解码器,但是字节码器能是父解码器。该标签包含的内容可以是任何解码器的名称。下面是该标签使用示例,示例中decoder_junior解码器的父解码器名称为decoder_father。
<decoder name="decoder_junior">
<parent>decoder_father</parent>
</decoder>
1.2.3 accumulate
该标签的作用是允许Wazuh跟踪跨多个日志消息的事件,基于一个已解码的ID。这在处理跨越多行或多个条目的日志时特别有用。需要注意的是,使用该标签要求通过正则表达式填充id字段。如果你有一系列的日志条目,它们都属于同一个会话或事件,并且你想要将它们组合在一起进行分析,accumulate 标签就会非常有用。这样,即使信息分布在多个日志条目中,Wazuh也能够将相关的数据字段聚合在一起。下面示例选自Wazuh内置解码器文件/var/ossec/ruleset/decoders/0185-openldap_decoders.xml中。
<decoder name="openldap">
<program_name>^slapd</program_name>
<accumulate/>
</decoder>
<decoder name="openldap-connect_ipv6">
<parent>openldap</parent>
<prematch>ACCEPT from IP=[</prematch>
<regex>^conn=(\d+) fd=\d+ ACCEPT from IP=[(\S+)]:\d+ \(IP=[(\S+)]:</regex>
<order>id, srcip, dstip</order>
<accumulate/>
</decoder>
1.2.4 program_name
该标签定义了一个条件,即如果所解析的日志中包含程序名,且程序名与该标签定义的程序名一致,那么此解码器就会应用到该日志的解析执行上。该标签内容可以是正则表达式、字符串或使用PCRE2语法的表达式。该标签包含一个可选属性为type,说明如下表所示:
属性 | 描述 | 取值范围 | 默认值 |
---|---|---|---|
type | 标识该标签内容格式 | osmatch osregex pcre2 | osmatch |
下面示例中,该解码器将会对程序名为test的应用产生的日志进行解码操作:
<decoder name="test_decoder">
<program_name>test</program_name>
</decoder>
1.2.5 prematch
该标签用于定义一个正则表达式,这个正则表达式是是否执行当前解码器的条件之一。如果日志消息匹配该标签中定义的正则表达式,那么解码器就会应用到该日志消息上。该标签通常用于识别日志消息的开始部分,以确保只有符合特定模式的日志消息才会被进一步解码。该标签的正则表达式匹配是在日志消息的正文中进行的,不考虑任何类似Syslog的头部信息。如果日志消息包含Syslog头部,则仅分析头部之后的内容。如果日志消息不包含Syslog头部,则整个日志消息都会被分析。下表为该标签的可选属性说明:
属性 | 描述 | 取值范围 | 默认值 |
---|---|---|---|
offset | 指定解码器执行匹配时距离日志起始位置偏移 | after_regex after_parent | |
type | 标识该标签内容格式 | osregex pcre2 | osregex |
after_parent: 当一个解码器定义为另一个解码器的子解码器时,after_parent 属性指定了解码器处理应开始于父解码器匹配内容之后的位置。这允许子解码器在父解码器已经匹配并处理了日志的一部分之后,继续处理剩余的日志内容。这种机制特别有用于处理嵌套或分层的日志格式,其中父解码器负责匹配日志的初始部分,而子解码器则负责进一步提取详细信息。 after_prematch: 这个属性用于指定解码器处理应开始于 prematch 匹配内容之后的位置。prematch 是解码器用来预匹配日志条目的一个标签,它定义了一个正则表达式,用于确定日志条目是否应该由该解码器处理。当 regex 标签中设置了 after_prematch 属性时,它会告诉解码器跳过 prematch 匹配的部分,并从其后开始进行进一步的匹配和数据提取。
下面示例中,解码器auditd-syscall执行解码的条件是父解码器auditd命中,且父解码器所匹配内容之后的日志中包含SYSCALL字符串。
<decoder name="auditd-syscall">
<parent>auditd</parent>
<prematch offset="after_parent">^SYSCALL </prematch>
<regex offset="after_parent">^(SYSCALL) msg=audit\(\d\d\d\d\d\d\d\d\d\d.\d\d\d:(\d+)\): </regex>
<order>audit.type,audit.id</order>
</decoder>
1.2.6 regex
该标签用于定义一个正则表达式来匹配和提取日志消息中的特定数据。该标签是解码器中非常重要的部分,因为它决定了解码器如何从日志中识别和抽取信息。在使用该标签时,还必须定义一个order标签。此外,regex标签需要在同一解码器上定义一个 prematch或program_name标签,或者在一个定义了prematch或program_name标签的父解码器上定义。下面是改标签支持的可选属性。
属性 | 描述 | 取值范围 | 默认值 |
---|---|---|---|
offset | 指定解码器执行匹配时距离日志起始位置偏移 | after_regex after_parent after_prematch | |
type | 标识该标签内容格式 | osregex pcre2 | osregex |
after_prematch:这个属性告诉解码器跳过 prematch 匹配的内容,并从 prematch 之后的位置开始应用 regex 正则表达式。
下面示例中,解码器auditd-syscall解码器所有执行条件都命中后执行解码操作,并根据<regex>标签中定义的正则表达式从日志中提取audit.type和audit.id字段信息。
<decoder name="auditd-syscall">
<parent>auditd</parent>
<prematch offset="after_parent">^SYSCALL </prematch>
<regex offset="after_parent">^(SYSCALL) msg=audit\(\d\d\d\d\d\d\d\d\d\d.\d\d\d:(\d+)\): </regex>
<order>audit.type,audit.id</order>
</decoder>
1.2.7 order
该标签用于指定从日志消息中提取的数据字段的顺序。当regex标签中的正则表达式匹配并捕获了多个子字符串时,order标签定义了这些捕获字段在解码器输出中的排列顺序。改标签包含两种字段类型,分别是静态字段和动态字段。两种字段类型如下表所示:
字段类型 | 值 | 描述 |
---|---|---|
静态字段 | srcuser dstuser user srcip dstip srcport dstport protocol system_name id url action status data extra_dat | 源用户名 目的用户名 用户名(同dstuser,两者只能用一个) 源IP 目的IP 源端口 目的端口 协议类型 系统名 事件ID URL 事件行为(deny、drop、accept等) 事件状态(success、failure等) 数据 额外数据 |
动态字段 | 除静态字段名外其它任何用户名称 |
下面示例中,解码器clamd-found依据regex标签中定义的正则表达式从日志中依次提取信息并命名为url、extra_data和id。
<decoder name="clamd-found">
<parent>clamd</parent>
<prematch>FOUND</prematch>
<regex>(\S+):\s+(\S+)\((\S+):</regex>
<order>url, extra_data, id</order>
</decoder>
1.2.8 fts
该标签用于记录特定字段的首次出现时间。这是一个有用的功能,可以帮助分析者追踪某个事件或数据第一次出现的时间点,从而对事件进行时间线分析或确定潜在的安全威胁的起始时间。该标签与order标签关联,存储对应字段首次出现时间。下面示例中,解码器example_decoder中fts标签与username字段关联,用于记录不同用户名首次出现在日志的时间。这对于追踪新用户活动或识别可能的未经授权的访问尝试非常有用。
<decoder name="example_decoder">
<program_name>^example_program</program_name>
<regex>user '(\w+)' logged in from</regex>
<order>username</order>
<fts>username</fts>
</decoder>
1.2.9 ftscomment
该标签用于添加与fts标签相关的注释。fts 标签记录特定字段的首次出现时间,而ftscomment则为这个记录提供额外的文本描述或上下文信息。这可以帮助分析人员更好地理解记录的时间戳背后的意义,尤其是在生成警报或进行日志审计时。下面是该标签的使用示例。
<decoder name="checkpoint-syslog-ids">
<parent>checkpoint-syslog</parent>
<type>ids</type>
<prematch offset="after_parent">^monitor|^drop</prematch>
<regex offset="after_prematch">attack:\s*(\.+);\s*</regex>
<regex>src:\s*(\S+);\s*dst:\s*(\S+);\s*</regex>
<regex>proto:\s*(\S+);</regex>
<order>extra_data, srcip, dstip, protocol</order>
<fts>name, extra_data, srcip, dstip</fts>
<ftscomment>First time Checkpoint rule fired.</ftscomment>
</decoder>
1.2.10 plugin_decoder
该标签用于指定一个插件来执行解码操作。当日志数据的格式或结构复杂到无法通过标准的正则表达式(regex)来提取信息时,这个标签就非常有用。例如,当处理JSON或XML格式的日志时,可以使用该标签来调用专门的插件进行解码。该标签允许的取值范围如下表所示:
插件名称 | 描述 |
---|---|
PF_Decoder | 这个插件用于解析 pfSense 防火墙的日志。 |
SymantecWS_Decoder | 这个解码器用于解析Symantec Web Security(WSS)或Symantec Email Security(SES)的日志。 |
SonicWall_Decoder | 用于解析 SonicWall 防火墙设备的日志。 |
OSSECAlert_Decoder | 这个解码器用于解析由 OSSEC 代理生成的警报。 |
JSON_Decoder | 用于解析 JSON 格式的日志。 |
下面是该标签支持的属性列表:
属性 | 取值范围 |
---|---|
offset | after_parent after_prematch |
下面示例中,解码器json将使用JSON_Decoder插件来解析匹配中的日志内容。
<decoder name="json">
<prematch>^{\s*"</prematch>
<plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>
1.2.11 use_own_name
该标签用于子解码器中,当设置为true时,它允许子解码器使用自己在decodeer标签name属性中定义的名称,而不是使用父解码器的名称。这在处理日志条目时特别有用,当你希望基于子解码器提取的数据创建规则或警报时,这个选项可以提供更清晰和具体的目标。例如,如果你有一个父解码器groupmod,它用于识别日志条目的开始部分,然后有一个子解码器groupmod-fields用于提取具体的数据字段,你可以设置use_own_name为true,这样在创建规则时就可以明确地引用groupmod-fields来匹配特定的数据。使用示例如下:
<decoder name="postfix-reject">
<use_own_name>true</use_own_name>
<parent>postfix</parent>
<prematch>^NOQUEUE: reject: \w\w\w\w from </prematch>
<regex offset="after_prematch">[(\S+)]: (\d+) |[(\S+)]:\d+: (\d+) </regex>
<order>srcip,id</order>
</decoder>
1.2.12 json_null_field
该标签用于处理JSON数据中的空值。仅适用于JSON解码器。下面是该标签允许的值范围:
取值范围 | 描述 |
---|---|
string | 将空值以字符串NULL的形式显示。 |
discard | 直接丢弃空值,并且不会将其存储在告警日志中。 |
1.2.12 json_array_structure
该标签用于指定如何处理JSON日志中的数组结构。仅适用于JSON解码器。下面是该标签允许的值范围:
取值范围 | 描述 |
---|---|
array | 这是默认值,表示将 JSON 数组结构保持为 JSON 格式的数组。在解码后的日志中,数组元素将作为 JSON 数组的形式展示。 |
csv | 表示将 JSON 数组结构转换为逗号分隔值(CSV)的字符串。当数组中的元素较多或者你希望以一种更简洁的方式展示数组内容时,这个选项非常有用。 |
1.2.13 var
该标签定义一个变量值,且该变量值可在当前解码器文件所包含的任意解码器中引用。它必须定义在文件的开头位置。下面是使用示例:
<var name="header">myprog</var>
<var name="offset">after_parent</var>
<var name="type">syscall</var>
<decoder name="syscall">
<prematch>^$header</prematch>
</decoder>
<decoder name="syscall-child">
<parent>syscall</parent>
<prematch offset="$offset">^: $type </prematch>
<regex offset="after_prematch">(\S+)</regex>
<order>syscall</order>
</decoder>
1.2.14 type
该标签用于指定解码器将要匹配的日志类型。这个标签的值通常与日志数据的格式或来源相关联,它可以帮助 Wazuh 更精确地处理和分析特定类型的日志数据。该标签的取值范围如下表所示:
取值范围 | 描述 |
---|---|
syslog | 系统日志类型,默认值 |
firewall | 防火墙日志类型 |
ids | 入侵检测日志类型 |
web-log | web日志类型 |
squid | Squid日志类型 |
windows | Windows日志类型 |
host-information | 主机信息类型 |
ossec | ossec日志类型 |
下面是改标签的使用示例,解码器dragon-nids主要针对IDS类型的日志进行解码操作。
<decoder name="dragon-nids">
<type>ids</type>
<prematch>^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\|</prematch>
<regex offset="after_prematch">^\S+\|(\S+)\|</regex>
<regex>(\S+)\|(\S+)\|</regex>
<order>id, srcip, dstip</order>
<fts>name, id, srcip, dstip</fts>
</decoder>
1.3 JSON解码器
JSON解码器能够提取数字、字符串、布尔值、空值、数组和对象等数据类型。提取的字段被存储为动态字段(即不属于Wazuh内置类型字段),可以被规则引用。[对于JSON解码器的详细介绍可阅读 【主机入侵检测】Wazuh解码器之JSON解码器文章。
1.4 解码器之间的关系
在 Wazuh 的解码器体系中,解码器之间可以相互独立,可以建立父子关系,也可以建立兄弟关系。其中建立兄弟关系的解码器称为兄弟解码器(sibling decoders),其要求多个解码器在同一层级上操作,它们之间没有父子关系。与父子解码器不同,父解码器基于特定条件触发其子解码器,兄弟解码器彼此独立且并行工作。这种方法在处理需要多种解码策略的日志或当日志条目的不同部分需要分别处理时特别有用。兄弟解码器提供了解码复杂日志结构的更大灵活性,并允许对日志数据进行更细致的分析。
1.4.1 父子解码器
父子解码器以及独立的解码器对日志消息分析步骤如下:
- 顺序检查:Wazuh的分析引擎会按照解码器配置的顺序,使用没有父解码器的解码器来检查每个日志消息。
- 匹配条件:当一个日志消息与某个解码器的匹配条件相符合时,就会触发该解码器。
- 重复过程:一旦某个解码器匹配成功,分析过程会重复,但这次仅限于使用该解码器作为父解码器的子解码器。
- 停止搜索:一旦某个解码器匹配成功,分析引擎就会停止搜索其他的解码器,而只专注于处理该解码器的子解码器(如果有的话)。
此匹配机制优势:
- 专注子解码器:这种机制确保了一旦确定了正确的解码路径,就会专注于沿着这个路径处理日志消息,而不是无休止地尝试所有可能的解码器。
- 有效触发:通过精确的匹配条件,可以确保只有相关的解码器被触发,这样可以提高分析的准确性和效率。
需要注意:
- 为了避免误报并确保正确有效地触发解码器,构建解码器时必须避免使用过于泛化的匹配条件。
- 子解码器不能再充当父解码器,即没有孙子解码器。
下面是父子解码器解析日志示意图:
1.4.2 兄弟解码器
兄弟解码器指在解码器层级结构中没有直接父子关系的一组解码器。它们可以被视为彼此的“父解码器”,这种设计允许它们在匹配日志时相互协作。当兄弟解码器中的任何一个匹配成功时,它不仅会处理自己的日志部分,还会触发检查其他兄弟解码器,这些解码器可以同时提取日志中的其他信息。由于兄弟解码器可以并行工作,它们可以同时从日志中提取多个信息片段。这意味着每个解码器可以专注于提取日志中的特定数据,而不会干扰其他解码器的操作。这种机制提高了解码器的灵活性,因为它们可以独立于彼此工作,同时在需要时协同处理复杂的日志结构。
下面是父子解码器解析日志示意图:
1.4.3 解码器间如何建立关系
前面在介绍解码器规则时提到标签的作用,那么如何建立父子解码器呢?只需要在子解码器中使用标签标明其父解码器的名称即可,下面示例中,解码器agent-buffer为解码器wazuh的子解码器。
<decoder name="wazuh">
<prematch>^wazuh: </prematch>
</decoder>
<decoder name="agent-buffer">
<parent>wazuh</parent>
<prematch offset="after_parent">^Agent buffer:</prematch>
<regex offset="after_prematch">^ '(\S+)'.</regex>
<order>level</order>
</decoder>
如何建立兄弟解码器呢?选择一个解码器作为根解码器(可以理解为兄弟中的老大),然后其它兄弟解码器与根解码器的名称相同,且用标签标明解码器名称,下面示例中创建了三个兄弟解码器,解码器的名称均为securityapp。
<decoder name="securityapp">
<program_name>securityapp</program_name>
</decoder>
<decoder name="securityapp">
<parent>securityapp</parent>
<regex>^(\w+):</regex>
<order>type</order>
</decoder>
<decoder name="securityapp">
<parent>securityapp</parent>
<regex>srcuser="(\.+)"</regex>
<order>srcuser</order>
</decoder>
1.5 自定义解码器
Wazuh支持用户通过自定义解码器来满足实际需求。
1.5.1 新增解码器
新增的自定义解码器建议在/var/ossec/etc/decoders/local_decoder.xml文件中添加或者在/var/ossec/etc/decoders/文件夹中添加。好处就是Wazuh升级时不会将用户新增的解码器配置覆盖掉。
假若想要解析下面格式的日志,且Wazuh内置解码器中没有针对此日志格式解析的解码器:
Dec 25 20:45:02 MyHost example[12345]: User ‘admin’ logged from ‘192.168.1.100’
在/var/ossec/etc/decoders/local_decoder.xml文件中添加解析上述日志内容的解码器,配置如下:
<decoder name="example">
<program_name>^example</program_name>
</decoder>
<decoder name="example">
<parent>example</parent>
<regex>User '(\w+)' logged from '(\d+.\d+.\d+.\d+)'</regex>
<order>user, srcip</order>
</decoder>
完成添加自定义解码器后,重启Wazuh Manager程序,并参考1.1 示例运行章节说明,使用wazuh-logtest工具对上述日志进行解码测试,输入结果如下:
Type one log per line
Dec 25 20:45:02 MyHost example[12345]: User 'admin' logged from '192.168.1.100'
**Phase 1: Completed pre-decoding.
full event: 'Dec 25 20:45:02 MyHost example[12345]: User 'admin' logged from '192.168.1.100''
timestamp: 'Dec 25 20:45:02'
hostname: 'MyHost'
program_name: 'example'
**Phase 2: Completed decoding.
name: 'example'
dstuser: 'admin'
srcip: '192.168.1.100'
1.5.2 修改内置解码器
修改Wazuh内置解码器的方法可以是直接修改内置解码器的配置文件内容,内置解码器配置文件在/var/ossec/ruleset/decoders/路径下。需要注意的是,此种修改方法在Wazuh进行升级的时候,会出现覆盖导致修改失效。另一种方法是将解码器的配置文件拷贝到/var/ossec/etc/decoders/路径下,并在/var/ossec/etc/ossec.conf配置文件中通过<decoder_exclude>标签将源文件排除。例如要修改/var/ossec/ruleset/decoders/0310-ssh_decoders.xml文件中的某个解码器,将0310-ssh_decoders.xml文件拷贝到/var/ossec/etc/decoders/下,并使用<decoder_exclude>标签将该文件排除,如下所示:
<ruleset>
<!-- User-defined ruleset -->
<decoder_dir>etc/decoders</decoder_dir>
<rule_dir>etc/rules</rule_dir>
<decoder_exclude>ruleset/decoders/0310-ssh_decoders.xml</decoder_exclude>
</ruleset>