规则格式 ============ 签名在Suricata中扮演着非常重要的角色。大多数情况下,人们会使用现有的规则集。 官方安装规则集的方法在 :doc:`../rule-management/suricata-update` 中有描述。 通过suricata-update可以使用许多免费规则集。为了帮助学习编写规则,Emerging Threats Open规则集是免费的,并且是一个很好的参考,包含了广泛的签名示例。 这份Suricata规则文档详细解释了签名;如何阅读、调整和创建它们。 一个规则/签名由以下部分组成: * **动作**,决定规则匹配时会发生什么。 * **头部**,定义协议、IP地址、端口和规则的方向。 * **规则选项**,定义规则的具体内容。 .. role:: example-rule-action .. role:: example-rule-header .. role:: example-rule-options .. role:: example-rule-emphasis 以下是一个规则的示例: .. container:: example-rule :example-rule-action:`alert` :example-rule-header:`http $HOME_NET any -> $EXTERNAL_NET any` :example-rule-options:`(msg:"HTTP GET Request Containing Rule in URI"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"rule"; fast_pattern; classtype:bad-unknown; sid:123; rev:1;)` 在这个示例中,:example-rule-action:`红色` 是动作, :example-rule-header:`绿色` 是头部,:example-rule-options:`蓝色` 是选项。 我们将使用上述签名作为本节示例,突出签名的不同部分。 .. _actions: 动作 ------ .. container:: example-rule :example-rule-emphasis:`alert` http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP GET Request Containing Rule in URI"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"rule"; fast_pattern; classtype:bad-unknown; sid:123; rev:1;) 有效的动作包括: * alert - 生成警报。 * pass - 停止进一步检查数据包。 * drop - 丢弃数据包并生成警报。 * reject - 向匹配数据包的发送者发送RST/ICMP不可达错误。 * rejectsrc - 与 `reject` 相同。 * rejectdst - 向匹配数据包的接收者发送RST/ICMP错误数据包。 * rejectboth - 向对话双方发送RST/ICMP错误数据包。 .. note:: 在IPS模式下,使用任何 `reject` 动作也会启用 `drop`。 更多信息请参见 :ref:`suricata-yaml-action-order`。 协议 -------- .. container:: example-rule alert :example-rule-emphasis:`http` $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP GET Request Containing Rule in URI"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"rule"; fast_pattern; classtype:bad-unknown; sid:123; rev:1;) 签名中的这个关键字告诉Suricata它涉及哪个协议。您可以在四种基本协议之间选择: * tcp(用于tcp流量) * udp * icmp * ip(ip代表“全部”或“任意”) 还有一些与TCP相关的额外协议选项: * tcp-pkt(用于匹配单个tcp数据包中的内容) * tcp-stream(仅用于匹配重组后的tcp流中的内容) 还有一些所谓的应用层协议或第7层协议可供选择。这些包括: * http(HTTP1或HTTP2) * http1 * http2 * ftp * tls(包括ssl) * smb * dns * dcerpc * dhcp * ssh * smtp * imap * pop3 * modbus(默认禁用) * dnp3(默认禁用) * enip(默认禁用) * nfs * ike * krb5 * bittorrent-dht * ntp * dhcp * rfb * rdp * snmp * tftp * sip * websocket 这些协议的可用性取决于配置文件suricata.yaml中是否启用了该协议。 如果您的签名中协议声明为'http',Suricata会确保该签名仅在TCP流中包含http流量时匹配。 源和目标 ---------------------- .. container:: example-rule alert http :example-rule-emphasis:`$HOME_NET` any -> :example-rule-emphasis:`$EXTERNAL_NET` any (msg:"HTTP GET Request Containing Rule in URI"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"rule"; fast_pattern; classtype:bad-unknown; sid:123; rev:1;) *第一个突出部分是流量源,第二个是流量目标(注意方向箭头的方向)。* 通过源和目标,您可以分别指定流量的来源和目的地。您可以分配IP地址(支持IPv4和IPv6)和IP范围。这些可以与操作符结合使用: ============== ========================= 操作符 描述 ============== ========================= ../.. IP范围(CIDR表示法) ! 例外/否定 [.., ..] 分组 ============== ========================= 通常,您还会使用变量,如 ``$HOME_NET`` 和 ``$EXTERNAL_NET``。suricata.yaml配置文件指定了这些变量涉及的IP地址。相应的 ``$HOME_NET`` 和 ``$EXTERNAL_NET`` 设置将替换规则中的变量。 更多信息请参见 :ref:`suricata-yaml-rule-vars`。 规则使用示例: ================================== ========================================== 示例 含义 ================================== ========================================== !1.1.1.1 除1.1.1.1外的所有IP地址 ![1.1.1.1, 1.1.1.2] 除1.1.1.1和1.1.1.2外的所有IP地址 $HOME_NET yaml中设置的HOME_NET [$EXTERNAL_NET, !$HOME_NET] EXTERNAL_NET且不包括HOME_NET [10.0.0.0/24, !10.0.0.5] 10.0.0.0/24,不包括10.0.0.5 [..., [....]] [..., ![.....]] ================================== ========================================== .. warning:: 如果您将配置设置为如下内容:: HOME_NET: any EXTERNAL_NET: !$HOME_NET 您不能使用 ``$EXTERNAL_NET`` 编写签名,因为它会评估为“非任意”,这是一个无效值。 .. note:: 请注意,源和目标地址也可以通过 ``ip.src`` 和 ``ip.dst`` 关键字匹配(参见 :ref:`ipaddr`)。这些关键字通常与数据集功能一起使用(参见 :ref:`datasets`)。 端口(源和目标) ------------------------------ .. container:: example-rule alert http $HOME_NET :example-rule-emphasis:`any` -> $EXTERNAL_NET :example-rule-emphasis:`any` (msg:"HTTP GET Request Containing Rule in URI"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"rule"; fast_pattern; classtype:bad-unknown; sid:123; rev:1;) *第一个突出部分是源端口,第二个是目标端口(注意方向箭头的方向)。* 流量通过端口进出。不同的协议有不同的端口号。例如,HTTP的默认端口是80,而443通常是HTTPS的端口。但请注意,端口并不决定通信中使用的协议,而是决定哪个应用程序接收数据。 上述端口通常是目标端口。源端口,即发送数据包的应用程序,通常由操作系统分配一个随机端口。当为您自己的HTTP服务编写规则时,通常会写 ``any -> 80``,因为这意味着从任何源端口到您的HTTP应用程序(运行在端口80上)的数据包都会被匹配。 在设置端口时,您也可以使用特殊操作符。操作符如: ============== ================== 操作符 描述 ============== ================== : 端口范围 ! 例外/否定 [.., ..] 分组 ============== ================== 规则使用示例: ============== ========================================== 示例 含义 ============== ========================================== [80, 81, 82] 端口80、81和82 [80: 82] 从80到82的范围 [1024: ] 从1024到最高端口号 !80 除80外的所有端口 [80:100,!99] 从80到100的范围,不包括99 [1:80,![2,4]] 从1到80的范围,不包括端口2和4 [.., [..,..]] ============== ========================================== 方向 --------- .. container:: example-rule alert http $HOME_NET any :example-rule-emphasis:`->` $EXTERNAL_NET any (msg:"HTTP GET Request Containing Rule in URI"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"rule"; fast_pattern; classtype:bad-unknown; sid:123; rev:1;) 方向箭头指示签名将被评估的方向。在大多数签名中,使用向右的箭头(``->``)。这意味着只有具有相同方向的数据包才能匹配。 还有双箭头(``=>``),它像 ``->`` 一样尊重方向性,但允许匹配双向事务,与匹配每个方向的关键字一起使用。 最后,也可以让规则匹配任一方向(``<>``):: source -> destination source => destination source <> destination (任一方向) 以下示例说明了方向。在这个示例中,有一个IP地址为1.2.3.4的客户端使用端口1024。一个IP地址为5.6.7.8的服务器监听端口80(通常是HTTP)。客户端向服务器发送消息,服务器回复其答案。 .. image:: intro/TCP-session.png 现在,假设我们有一个规则,其头部如下:: alert tcp 1.2.3.4 1024 -> 5.6.7.8 80 只有从客户端到服务器的流量会被此规则匹配,因为方向指定了我们不想评估响应数据包。 现在,如果我们有一个规则,其头部如下:: alert tcp 1.2.3.4 any <> 5.6.7.8 80 Suricata会复制它,并在两个方向上使用相同的规则头部: alert tcp 1.2.3.4 any -> 5.6.7.8 80 alert tcp 5.6.7.8 80 -> 1.2.3.4 any .. warning:: 没有“反向”风格的方向,即没有 ``<-``。 事务性规则 ~~~~~~~~~~~~~~~~~~~ 以下是一个事务性规则的示例: .. container:: example-rule alert http any any :example-rule-emphasis:`=>` 5.6.7.8 80 (msg:"matching both uri and status"; sid: 1; http.uri; content: "/download"; http.stat_code; content: "200";) 它将匹配流向5.6.7.8和端口80的流量。 并且它将匹配完整的事务,使用请求中的uri和响应中的stat_code。 因此,只有当Suricata同时获取请求和响应时才会匹配。 事务性规则可以使用方向模糊的关键字,通过指定方向。 .. container:: example-rule alert http any any => 5.6.7.8 80 (msg:"matching json to server and xml to client"; sid: 1; http.content_type: :example-rule-emphasis:`to_server`; content: "json"; http.content_type: :example-rule-emphasis:`to_client`; content: "xml";) 事务性规则有一些限制: * 它们不能使用方向模糊的关键字。 * 它们仅适用于首先向服务器发送请求,然后向客户端发送响应的事务,而不是相反(未经测试)。 * 如果它们还在服务器方向上有流缓冲区,则不能有 ``fast_pattern`` 或 ``prefilter`` 到客户端方向,参见下面的示例。 * 如果单个方向性规则足够,它们将拒绝加载。 此规则不能有 ``fast_pattern`` 到客户端,因为 ``file.data`` 是一个流缓冲区,并且会拒绝加载。 .. container:: example-rule alert http any any => any any (file.data: to_server; content: "123"; http.stat_code; content: "500"; fast_patten;) 如果没有明确指定,事务性规则将默认选择服务器方向的 ``fast_pattern``。 规则选项 ------------ 规则的其余部分由选项组成。这些选项用括号括起来,并用分号分隔。一些选项有设置(如 ``msg``),由选项的关键字后跟冒号和设置指定。其他选项没有设置;它们只是关键字(如 ``nocase``):: <关键字>: <设置>; <关键字>; 规则选项有特定的顺序,改变它们的顺序会改变规则的含义。 .. note:: 字符 ``;`` 和 ``"`` 在Suricata规则语言中有特殊含义,必须在规则选项值中转义。例如:: msg:"Message with semicolon\;"; 因此,您还必须转义反斜杠,因为它作为转义字符。 本文档的其余部分记录了各种关键字的使用。 以下是一些关于关键字的通用细节。 禁用警报 ~~~~~~~~~~~~~~~~ 有一种方法可以使用关键字 ``noalert`` 禁用规则的警报生成。当此关键字是规则的一部分时,如果规则的其他部分匹配,则不会生成警报。也就是说,其他规则动作 *仍将被应用*。使用 ``noalert`` 可以帮助规则使用 `flowbits`、`datasets` 或其他规则语言的状态维护构造来收集或设置状态。参见 :doc:`thresholding` 了解其他控制警报频率的方法。 以下规则展示了 ``noalert`` 的熟悉模式: * 第一条规则标记状态而不生成警报。 * 第二条规则如果状态已设置且满足其他条件,则生成警报。 .. container:: example-rule :example-rule-action:`alert` :example-rule-header:`http any any -> $HOME_NET any` :example-rule-options:`(msg:"noalert example: set state"; flow:established,to_server; xbits:set,SC.EXAMPLE,track ip_dst, expire 10; noalert; http.method; content:"GET"; sid:1; )` :example-rule-action:`alert` :example-rule-header:`http any any -> $HOME_NET any` :example-rule-options:`(msg:"noalert example: state use"; flow:established,to_server; xbits:isset,SC.EXAMPLE,track ip_dst; http.method; content:"POST"; sid: 2; )` 在IPS模式下,``noalert`` 通常用于Suricata应 `drop` 网络数据包而不生成警报的情况(如下示例)。以下规则是一个简化示例,展示了 ``noalert`` 如何在IPS部署中用于丢弃入站SSH请求。 .. container:: example-rule :example-rule-action:`drop` :example-rule-header:`tcp any any -> any 22` :example-rule-options:`(msg:"Drop inbound SSH traffic"; noalert; sid: 3)` .. _rules-modifiers: 修饰关键字 ~~~~~~~~~~~~~~~~~ 一些关键字作为修饰符。有两种类型的修饰符。 * 较旧风格的 **'内容修饰符'** 会回溯规则,例如:: alert http any any -> any any (content:"index.php"; http_uri; sid:1;) 在上面的示例中,模式'index.php'被修改为检查HTTP uri缓冲区。 * 较新的类型称为 **'粘性缓冲区'**。它将缓冲区名称放在前面,所有后续关键字都应用于该缓冲区,例如:: alert http any any -> any any (http_response_line; content:"403 Forbidden"; sid:1;) 在上面的示例中,模式'403 Forbidden'被检查HTTP响应行,因为它跟在 ``http_response_line`` 关键字之后。 .. _rules-normalized-buffers: 规范化缓冲区 ~~~~~~~~~~~~~~~~~~ 数据包由原始数据组成。HTTP和重组会复制这些类型的数据包数据。它们会消除异常内容,合并数据包等。剩下的被称为“规范化缓冲区”: .. image:: normalized-buffers/normalization1.png 因为数据被规范化,所以它不再是原来的样子;它是一种解释。规范化缓冲区包括:所有HTTP关键字、重组流、TLS、SSL、SSH、FTP和dcerpc缓冲区。 请注意,有一些例外,例如 ``http_raw_uri`` 关键字。更多信息请参见 :ref:`rules-http-uri-normalization`。