.. _datasets: 数据集 ====== 使用 ``dataset`` 和 ``datarep`` 关键字可以匹配大量数据到任何粘性缓冲区。 例如,匹配名为 ``dns-bl`` 的DNS黑名单:: dns.query; dataset:isset,dns-bl; 这些关键字支持转换操作。例如,通过MD5黑名单检查DNS查询:: dns.query; to_md5; dataset:isset,dns-bl; 全局配置(可选) ---------------- 数据集可以选择在主配置中定义。集合也可以通过规则语法声明。 跟踪唯一值的集合示例:: datasets: ua-seen: type: string state: ua-seen.lst dns-sha256-seen: type: sha256 state: dns-sha256-seen.lst 与上述配置配套的规则: .. container:: example-rule alert dns any any -> any any (msg:"dns list test"; dns.query; to_sha256; dataset:isset,dns-sha256-seen; sid:123; rev:1;) .. container:: example-rule alert http any any -> any any (msg: "http user-agent test"; http.user_agent; dataset:set,ua-seen; sid:234; rev:1;) 还可以选择定义全局默认的memcap和hashsize。 示例:: datasets: defaults: memcap: 100mb hashsize: 2048 ua-seen: type: string load: ua-seen.lst 或者为每个数据集单独定义memcap和hashsize。 示例:: datasets: ua-seen: type: string load: ua-seen.lst memcap: 10mb hashsize: 1024 .. note:: `hashsize` 应接近数据集中的条目数量以避免冲突。如果设置过低,可能导致启动时间较长。 规则关键字 ---------- dataset ~~~~~~~ 数据集是二元的:数据要么在集合中,要么不在。 语法:: dataset:,,; dataset:, \ [, type , save , load , state , memcap , hashsize , format , context_key , value_key , array_key , remove_key]; type 数据类型:string, md5, sha256, ipv4, ip load Suricata启动时加载数据的文件名 state 设置加载和保存数据集的文件名 save 高级选项,设置Suricata退出时保存内存数据的文件名 memcap 相应数据集的最大内存限制 hashsize 相应数据集的哈希大小允许值 format 文件格式:csv, json。默认为csv。参见 :ref:`dataset with json format ` 了解json 和ndjson选项 context_key 用于丰富警报事件的键 适用于json格式 value_key 用于警报值的键 适用于json格式 array_key 用于警报数组的键 适用于json格式 remove_key 如果设置,将从警报事件中移除由value_key指向的JSON对象 .. note:: 'type' 是必填项,必须设置。 .. note:: 'load' 和 'state' 或 'save' 和 'state' 不能混用。 示例规则如下: 1. 检测唯一的User-Agent: .. container:: example-rule alert http any any -> any any (msg:"LOCAL HTTP new UA"; http.user_agent; dataset:set,http-ua-seen, type string, state http-ua-seen.csv; sid:8000001; rev:1;) 2. 检测唯一的TLD: .. container:: example-rule alert dns $HOME_NET any -> any any (msg:"LOCAL DNS unique TLD"; dns.query; pcrexform:"\\.([^\\.]+)$"; dataset:set,dns-tld-seen, type string, state dns-tld-seen.csv; sid:8000002; rev:1;) 下图展示了 ``pcrexform`` 如何在域名上工作以在数据集 ``dns-tld-seen`` 中找到TLD: .. image:: dataset-examples/detect-unique-tlds.png 请注意,仅使用数据集无法完成某些操作(如上面的示例2),但可以结合其他规则关键字。不过要注意额外关键字的性能开销,例如在上面的第二个示例规则中,由于 ``pcrexform``,可能会对性能产生负面影响。 datarep ~~~~~~~ 数据信誉允许将数据与信誉列表进行匹配。 语法:: datarep:,,, \ [, load , type , memcap , hashsize ]; 示例规则如下:: alert dns any any -> any any (dns.query; to_md5; datarep:dns_md5, >, 200, load dns_md5.rep, type md5, memcap 100mb, hashsize 2048; sid:1;) alert dns any any -> any any (dns.query; to_sha256; datarep:dns_sha256, >, 200, load dns_sha256.rep, type sha256; sid:2;) alert dns any any -> any any (dns.query; datarep:dns_string, >, 200, load dns_string.rep, type string; sid:3;) 在这些示例中,DNS查询字符串被检查与三个不同的信誉列表:MD5列表、SHA256列表和原始字符串(缓冲区)列表。只有当数据在列表中且信誉值大于200时,规则才会匹配。 .. _datasets_json: dataset with JSON ~~~~~~~~~~~~~~~~~ dataset with JSON 允许将数据与集合进行匹配,并在事件中输出与匹配值关联的数据。 支持两种格式:``json`` 和 ``ndjson``。区别在于 ``json`` 格式是单个JSON对象,而 ``ndjson`` 处理每行一个JSON对象的文件。``ndjson`` 格式适用于大文件,因为解析是逐行进行的。 语法:: dataset:,,; dataset:, \ [, type , load , format , memcap , hashsize , context_key \ , value_key , array_key ]; 示例规则如下:: alert http any any -> any any (msg:"IP match"; ip.dst; dataset:isset,bad_ips, type ip, load bad_ips.json, format json, context_key bad_ones, value_key ip; sid:8000001;) 在此示例中,如果目标IP在集合中,则会触发匹配,并且警报将包含一个 ``alert.content.bad_ones`` 子对象,其中包含与该值关联的JSON数据(``bad_ones`` 来自 ``context_key`` 选项)。 当格式为 ``json`` 或 ``ndjson`` 时,``value_key`` 用于获取行(``ndjson`` 格式)或数组(``json`` 格式)中的值。数据文件中至少需要有一个元素包含 ``value_key`` 才能成功加载。 如果存在 ``array_key``,Suricata将提取对应的子对象(必须是JSON数组)并在该数组中搜索要添加到集合的元素。这仅适用于 ``json`` 格式。 如果不想在警报中包含 ``value_key``,可以使用 ``remove_key`` 选项。这将从警报事件中移除该键。 更多信息请参见 :ref:`Dataset with JSON format `。 规则重载 -------- 在yaml中定义的集合,或仅使用 `state` 或 `save` 的集合,被视为 `动态` 集合。这些集合在规则重载期间不会重新加载。 仅在规则中使用 `load` 定义的集合被视为 `静态` 测试。这些集合在运行时不应更改。在规则重载期间,这些集合会从磁盘重新加载。此重载在完整的规则重载过程完成后生效。 Unix Socket ----------- dataset-add ~~~~~~~~~~~ Unix Socket命令,用于向集合添加数据。成功后,添加会立即生效。 语法:: dataset-add set name 已定义数据集的名称 type 数据类型:string, md5, sha256, ipv4, ip data 序列化形式的数据(字符串为base64,md5/sha256为十六进制表示,ipv4/ip为字符串表示) 示例将'google.com'添加到集合'myset':: dataset-add myset string Z29vZ2xlLmNvbQ== dataset-remove ~~~~~~~~~~~~~~ Unix Socket命令,用于从集合中移除数据。成功后,移除会立即生效。 语法:: dataset-remove set name 已定义数据集的名称 type 数据类型:string, md5, sha256, ipv4, ip data 序列化形式的数据(字符串为base64,md5/sha256为十六进制表示,ipv4/ip为字符串表示) dataset-clear ~~~~~~~~~~~~~ Unix Socket命令,用于清除集合中的所有数据。成功后,清除会立即生效。 语法:: dataset-clear set name 已定义数据集的名称 type 数据类型:string, md5, sha256, ipv4, ip dataset-lookup ~~~~~~~~~~~~~~ Unix Socket命令,用于测试数据是否在集合中。 语法:: dataset-lookup set name 已定义数据集的名称 type 数据类型:string, md5, sha256, ipv4, ip data 测试数据的序列化形式(字符串为base64,md5/sha256为十六进制表示,ipv4/ip为字符串表示) 示例测试'google.com'是否在集合'myset'中:: dataset-lookup myset string Z29vZ2xlLmNvbQ== dataset-dump ~~~~~~~~~~~~ Unix socket命令,触发将数据集转储到磁盘。 语法:: dataset-dump dataset-add-json ~~~~~~~~~~~~~~~~ Unix Socket命令,用于向集合添加数据。成功后,添加会立即生效。 语法:: dataset-add-json set name 已定义数据集的名称 type 数据类型:string, md5, sha256, ipv4, ip data 序列化形式的数据(字符串为base64,md5/sha256为十六进制表示,ipv4/ip为字符串表示) 示例将'google.com'添加到集合'myset':: dataset-add-json myset string Z29vZ2xlLmNvbQ== {"city":"Mountain View"} 文件格式 -------- 数据集使用简单的CSV格式,每行一个数据。 数据类型 ~~~~~~~~ string 文件中为base64编码的字符串 md5 文件中为十六进制编码的字符串 sha256 文件中为十六进制编码的字符串 ipv4 文件中为字符串 ip 文件中为字符串,可以是IPv6或IPv4地址(标准表示法或IPv4 in IPv6表示法) dataset ~~~~~~~ 数据集结构简单,文件中每行一个数据。 语法:: 例如,ua-seen类型为string:: TW96aWxsYS80LjAgKGNvbXBhdGlibGU7ICk= 通过 ``base64 -d`` 解码后显示其值:: Mozilla/4.0 (compatible; ) datarep ~~~~~~~ datarep格式与dataset类似,但多一个CSV字段: 语法:: , .. _datajson_data: dataset with JSON enrichment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 如果 ``format json`` 用于dataset关键字的参数中,则加载的文件必须包含有效的JSON对象。 如果存在 ``value_key`` 选项,则文件必须包含一个有效的JSON对象,其中包含一个数组,且该数组中存在与 ``value_key`` 值相等的键。 例如,如果文件 ``file.json`` 如下所示(类似于REST API调用的返回):: { "time": "2024-12-21", "response": { "threats": [ {"host": "toto.com", "origin": "japan"}, {"host": "grenouille.com", "origin": "french"} ] } } 那么检查威胁列表的dataset with JSON可以定义为:: http.host; dataset:isset,threats,load file.json, context_key threat, value_key host, array_key response.threats; 如果签名匹配,将生成如下警报:: { "alert": { "context": { "threat": { "host": "toto.com", "origin": "japan" } } } } .. _datasets_file_locations: 文件位置 -------- 在 ``suricata.yaml`` 中配置的数据集文件名可以存在于文件系统的任何位置。 当在规则中指定数据集文件名时,适用以下 *规则*: - 对于 ``load``,文件名相对于包含该规则的规则文件打开。允许绝对文件名和父目录遍历。 - 对于 ``save`` 和 ``state``,文件名相对于 ``$LOCALSTATEDIR/suricata/data``。在许多安装中,这将是 ``/var/lib/suricata/data``,但运行 ``suricata --build-info`` 并检查 ``--localstatedir`` 的值以验证您安装中的位置。 - 除非配置参数 ``datasets.allow-absolute-filenames`` 设置为 ``true``,否则不允许绝对文件名或包含父目录遍历(``..``)的文件名。 .. _datasets_security: 安全性 ------ 由于数据集可能允许规则分发者通过 ``save`` 和 ``state`` 数据集规则对系统进行写访问,默认情况下允许的位置是严格的,但有两个数据集选项可以调整使用数据集文件名的规则的安全性:: datasets: rules: # 设置为true以允许在规则中使用绝对文件名和包含".."组件的文件名引用父目录。 allow-absolute-filenames: false # 允许规则中的数据集对"save"和"state"进行写访问。默认启用,但写访问仅限于数据目录。 allow-write: true 通过将 ``datasets.rules.allow-write`` 设置为false,所有 ``save`` 和 ``state`` 规则将无法加载。此选项默认启用以保持与之前Suricata 6.0版本的兼容性,但可能在未来的主要版本中更改。 通过将 ``datasets.rules.allow-absolute-filenames`` 设置为 ``true``,可以恢复Suricata 6.0.13之前的行为,但这样做将允许任何规则覆盖系统上Suricata具有写访问权限的任何文件。