Wazuh规则编写

Wazuh规则编写

  1. 安全
  2. 5 days ago
  3. 16 min read

Wazuh通过Agent、系统日志、syslog等方式收集日志,然后将日志数据交给Wazuh数据分析引擎进行处理。该引擎利用decoder将日志消息解析为有用的字段,然后将解析出来的字段和规则进行匹配。

Wazuh 数据分析引擎有以下职责:

  1. 日志收集:通过Agent等方式采集日志。

  2. 日志解码:Wazuh服务器使用解码器实时分析收集到的日志。解码器负责解析和规范化日志数据,将原始日志数据转换为统一的结构化格式,并提取Wazuh能够有效处理的最相关字段。

  3. 规则匹配和警报可视化:解码后,Wazuh服务器会将日志与其规则集进行比较,并在满足特定条件时触发警报。生成的警报记录在Wazuh服务器上的/var/ossec/logs/alerts/alerts.log 和 /var/ossec/logs/alerts/alerts.json 中。然后,使用 Filebeat 将日志转发并存储在Wazuh索引器中。

规则集目录结构

/var/ossec/
        ├─ etc/
        │   ├─ decoders/
        |   |        └─ local_decoder.xml
        │   └─ rules/
        |         └─ local_rules.xml
        └─ ruleset/
                ├─ decoders/
                └─ rules/

可以在 /var/ossec/ruleset/ 中找到所有开箱即用的规则和解码器。此目录中的所有文件在 Wazuh 升级过程中都会被覆盖或修改。因此,不建议在此处编辑或添加自定义文件。相反,建议在 /var/ossec/etc/ 目录中进行自定义更改。在这里,可以添加自己的解码器和规则文件,或者使用默认的 /var/ossec/etc/decoders/local_decoder.xml 和 /var/ossec/etc/rules/local_rules.xml 文件。

Decoder 解码器

Wazuh利用解码器从收到的日志消息中提取信息。收到日志消息后,解码器会将信息拆分成多个字段,以便进行分析。

Wazuh解码器使用XML语法,允许用户指定如何解析和规范化日志数据。该语法通常包含以下元素:(用于定义解码器)、(用于指定解码顺序)以及(用于定义用于模式匹配的正则表达式)。

解码器的运行分为两个阶段:预解码和解码。在预解码阶段,当出现类似 syslog 的标头时,会提取时间戳、主机名和程序名等常规信息。初始提取过程为进一步分析提供了必要的上下文信息。在随后的解码阶段,解码器会解析和解释剩余的日志数据,提取其他相关信息。它们在解析和解释日志数据方面发挥着至关重要的作用,使 Wazuh 能够理解并响应不同类型的事件。

Wazuh内置了专用于JSON格式日志的JSON解码器 ,同时还提供了一系列其他开箱即用的解码器。此外,用户还可以创建自定义解码器。

JSON解码器

Wazuh包含JSON日志的默认解码器,可以从任何来源提取此格式的数据。 JSON 解码器具有提取以下数据类型的能力:

数据类型描述
数字整数或十进制数。
字符串一系列字符。
布尔值为 true 或 false 。
空值空值
数组包含零个或多个值的列表。这些值可以不同,但​​必须属于上述值中的某些值。不支持对象数组。
对象键/值对的集合,其中键是字符串。

提取的字段存储为动态字段 ,可以通过规则引用。

以下示例展示了Wazuh如何解码JSON日志并为 Suricata 生成警报。

Suricata event log: Suricata 事件日志:

{
   "timestamp": "2023-05-02T17:46:48.515262+0000",
   "flow_id": 1234,
   "in_iface": "eth0",
   "event_type": "alert",
   "src_ip": "16.10.10.10",
   "src_port": 5555,
   "dest_ip": "16.10.10.11",
   "dest_port": 80,
   "proto": "TCP",
   "alert": {
      "action": "allowed",
      "gid": 1,
      "signature_id": 2019236,
      "rev": 3,
      "signature": "ET WEB_SERVER Possible CVE-2014-6271 Attempt in HTTP Version Number",
      "category": "Attempted Administrator Privilege Gain",
      "severity": 1
   },
   "payload": "21YW5kXBtgdW5zIGRlcHJY2F0QgYWI",
   "payload_printable": "this_is_an_example",
   "stream": 0,
   "host": "suricata.com"
}

JSON 解码器从 JSON 日志数据中提取每个字段以与规则进行比较,从而无需特定的 Suricata 解码器。

可以在 Wazuh 服务器上运行 /var/ossec/bin/wazuh-logtest 工具来测试日志样本并了解当前的解码情况。

偏移

Wazuh JSON 解码器中的 offset 属性可以通过丢弃输入字符串的某些部分来提取传入日志中包含的 JSON 数据。此功能在处理包含 JSON 有效负载之前的附加元数据或格式的日志时非常有用。例如,如果我们收到一个包含嵌入在较大字符串中的 JSON 数据的日志,我们可以使用 offset 属性丢弃前面的文本,只关注 JSON 内容。 比如有如下字符串

2018 Apr 04 13:11:52 nba_program: this_is_an_example: " player_information: "{ "name": "Stephen", "surname": "Curry", "team": "Golden State Warriors", "number": 30, "position": "point guard"}

通过使用带有 offset 属性的 JSON 解码器,可以高效地提取和处理 JSON 数据,以便进一步分析。使用 offset 属性的解码器声明如下:

<decoder name="raw_json">
    <program_name>nba_program</program_name>
    <prematch>player_information: "</prematch>
    <plugin_decoder offset="after_prematch">JSON_Decoder</plugin_decoder>
</decoder>

当使用 /var/ossec/bin/wazuh-logtest 测试日志样本时,我们获得以下输出:

Type one log per line

2018 Apr 04 13:11:52 nba_program: this_is_an_example: " player_information: "{ "name": "Stephen", "surname": "Curry", "team": "Golden State Warriors", "number": 30, "position": "point guard"}

**Phase 1: Completed pre-decoding.
        full event: '2018 Apr 04 13:11:52 nba_program: this_is_an_example: " player_information: "{ "name": "Stephen", "surname": "Curry", "team": "Golden State Warriors", "number": 30, "position": "point guard"}'
        timestamp: '2018 Apr 04 13:11:52'
        program_name: 'nba_program'

**Phase 2: Completed decoding.
        name: 'raw_json'
        name: 'Stephen'
        number: '30'
        position: 'point guard'
        surname: 'Curry'
        team: 'Golden State Warriors'

我们可以看到,JSON 解码器忽略了有效 JSON 对象之后的任何数据,从而确保准确提取 JSON 字段。

插件解码器与正则表达式的混合

另一个功能是将插件解码器与正则表达式结合起来的能力。

传入日志:

2018 Jun 08 13:11:52 nba_email_db: json_data: { "name": "Stephen", "surname": "Curry", "email": "[email protected]"}

我们可以从一个父级解码器设置多个子解码器,像之前一样指定一个插件解码器,也可以指定另一个包含正则表达式的解码器。例如,以下几个:

<decoder name="json_parent">
    <program_name>nba_email_db</program_name>
</decoder>

<decoder name="json_child">
    <parent>json_parent</parent>
    <prematch>json_data: </prematch>
    <plugin_decoder offset="after_prematch">JSON_Decoder</plugin_decoder>
</decoder>

<decoder name="json_child">
    <parent>json_parent</parent>
    <regex>@(\S+)"</regex>
    <order>email_domain</order>
</decoder>

使用 /var/ossec/bin/wazuh-logtest 测试日志样本时,我们可以观察到 JSON 解码器解码后的字段,以及正则表达式匹配的字段:

Type one log per line

2018 Jun 08 13:11:52 nba_email_db: json_data: { "name": "Stephen", "surname": "Curry", "email": "[email protected]"}

**Phase 1: Completed pre-decoding.
        full event: '2018 Jun 08 13:11:52 nba_email_db: json_data: { "name": "Stephen", "surname": "Curry", "email": "[email protected]"}'
        timestamp: '2018 Jun 08 13:11:52'
        program_name: 'nba_email_db'

**Phase 2: Completed decoding.
        name: 'json_parent'
        parent: 'json_parent'
        email: '[email protected]'
        email_domain: 'gmail.com'
        name: 'Stephen'
        surname: 'Curry'

动态字段

动态字段是在解码过程中从日志数据中提取的附加字段。与预定义字段不同,动态字段的数量不受限制,并且会根据日志消息的内容而变化。这些字段从日志中捕获特定信息,从而丰富可用于分析和检测的数据。

传统解码器

传统上,Wazuh 提供十三个预定义字段来存储提取的信息: user 、 srcip 、 dstip 、 srcport 、 dstport 、 protocol 、 action 、 id 、 url 、 data 、 extra_data 、 status 和 system_name 名称。这些也称为“静态字段”。但是,只能同时提取八个字段。出现这种限制是因为在某些情况下,当日志条目包含多种类型的信息时,Wazuh 会优先提取特定字段。因此,为了管理资源限制并保持日志处理的效率,只能同时填充十三个字段中的八个。在这种情况下优先考虑的字段通常是: user 、 srcip 、 dstip 、 srcport 、 dstport 、 protocol 、 action 和 id 。

可以在下面找到一个示例解码器来匹配一些静态字段:

<decoder name="web-accesslog">
  <type>web-log</type>
  <prematch>^\d+.\d+.\d+.\d+ - </prematch>
  <regex>^(\d+.\d+.\d+.\d+) - \S+ [\S+ -\d+] </regex>
  <regex>"\w+ (\S+) HTTP\S+ (\d+) </regex>
  <order>srcip,url,id</order>
</decoder>

动态解码器

通常需要从事件中提取八个以上的相关字段,而且提取的实际数据项通常与有限的预定义字段名称列表无关。考虑到在这些限制内操作的局限性,我们提供了无限数量的字段,其名称应准确反映提取的数据。此增强功能还支持嵌套字段名称。 可以在下面找到一个示例解码器来匹配一些动态字段:

<decoder name="auditd-config_change">
  <parent>auditd</parent>
  <regex offset="after_regex">^auid=(\S+) ses=(\S+) op="(\.+)"</regex>
  <order>audit.auid,audit.session,audit.op</order>
</decoder>

Wazuh 将标签中包含的任何字段名称转换为 JSON 字段。 以下示例显示了 /var/ossec/ruleset/decoders/0040-auditd_decoders.xml 解码器如何从警报中提取信息:

** Alert 1486483073.60589: - audit,audit_configuration,
2017 Feb 07 15:57:53 wazuh-example->/var/log/audit/audit.log
Rule: 80705 (level 3) -> 'Auditd: Configuration changed'
type=CONFIG_CHANGE msg=audit(1486483072.194:20): auid=0 ses=6 op="add rule" key="audit-wazuh-a" list=4 res=1
audit.type: CONFIG_CHANGE
audit.id: 20
audit.auid: 0
audit.session: 6
audit.op: add rule
audit.key: audit
audit.list: 4
audit.res: 1

JSON 输出

{
  "rule": {
    "level": 3,
    "description": "Auditd: Configuration changed",
    "id": 80705,
    "firedtimes": 2,
    "groups": [
      "audit",
      "audit_configuration"
    ]
  },
  "agent": {
    "id": "000",
    "name": "wazuh-example"
  },
  "manager": {
    "name": "wazuh-example"
  },
  "full_log": "type=CONFIG_CHANGE msg=audit(1486483072.194:20): auid=0 ses=6 op=\"add rule\" key=\"audit-wazuh-a\" list=4 res=1",
  "audit": {
    "type": "CONFIG_CHANGE",
    "id": "20",
    "auid": "0",
    "session": "6",
    "op": "add rule",
    "key": "audit",
    "list": "4",
    "res": "1"
  },
  "decoder": {
    "parent": "auditd",
    "name": "auditd"
  },
  "timestamp": "2017 Feb 07 15:57:53",
  "location": "/var/log/audit/audit.log"
}

默认情况下,从标签中可以同时提取的最大字段数为64。可以修改 /var/ossec/etc/internal_options.conf 文件中的 analysisd.decoder_order_size 变量来调整此值。

如果需要更改此值,将 analysisd.decoder_order_size 部分从 /var/ossec/etc/internal_options.conf 复制到 /var/ossec/etc/local_internal_options.conf ,并在那里进行必要的更改。

兄弟解码器 Sibling Decoders

兄弟解码器是指一种解码器构建策略,其中多个解码器在同一层级运行,彼此之间不存在父子关系。与传统的父子解码器关系(父解码器根据特定条件触发其子解码器)不同,兄弟解码器彼此独立并并行运行。当处理需要多种解码策略的日志,或需要分别处理日志条目的不同部分时,这种方法尤为有用。兄弟解码器在解码复杂的日志结构时提供了更大的灵活性,并允许对日志数据进行更细致的分析。

传统日志解码

Wazuh 从众多与环境安全相关的来源收集日志消息。随后,每条接收的消息都会基于简单且资源高效的逻辑进行分析,从而使 Wazuh 管理器能够以最少的资源处理大量日志数据。

分析过程包括使用没有父级的解码器按顺序检查每条日志消息。一旦满足匹配条件,该过程将使用以此解码器为父级的解码器重复进行。需要注意的是,一旦解码器匹配成功,它将停止搜索其他解码器,而只关注其子级(如果有)。因此,在构建解码器时,必须避免过于通用的匹配条件,以防止误报并确保有效触发合适的解码器。

提醒一下,与规则不同,解码器不能有“孙子”。换句话说,子解码器不能充当父解码器。

处理动态结构化日志

解码器级别的匹配过程使用正则表达式 ,这要求匹配的字符串具有特定的结构。然而,当日志不遵循特定结构时,这可能会带来麻烦。它们通常会省略部分日志或更改顺序来提供信息,这使得创建所有必要的解码器来匹配可能接收安全相关数据的所有可能组合变得不切实际,甚至不可能。

兄弟解码器利用简单的父子匹配逻辑,可以创建一组互为“父”的解码器。因此,当其中一个解码器匹配成功时,它还会检查“兄弟”解码器,并一次提取一条信息。

因此,即使信息的顺序发生变化、存在附加信息或缺少某些信息,Wazuh 分析引擎仍然可以从消息中提取尽可能多的信息。

通过同级解码器以模块化方式提取信息,显著提高了其可读性。这是通过将冗长的正则表达式字符串分解成更小、更易于管理的部分来实现的。

举例

提供以下日志消息:

Apr 12 14:31:38 hostname1 securityapp: INFO: srcuser="Bob" action="called" dstusr="Alice"

一个简单的解码器可能是:

<decoder name="securityapp">
  <program_name>securityapp</program_name>
  <regex>(\w+): srcuser="(\.+)" action="(\.+)" dstusr="(\.+)"</regex>
  <order>type,srcuser,action,dstuser</order>
</decoder>

参考

博客: htttps://colin404.com

Wazuh官方文档: https://documentation.wazuh.com/current/user-manual/ruleset/index.html

Wazuh 安全 security SOC SIEM SOAR