10.1. 规则格式

签名在Suricata中扮演着非常重要的角色。大多数情况下,人们会使用现有的规则集。

官方安装规则集的方法在 使用 Suricata-Update 管理规则 中有描述。

通过suricata-update可以使用许多免费规则集。为了帮助学习编写规则,Emerging Threats Open规则集是免费的,并且是一个很好的参考,包含了广泛的签名示例。

这份Suricata规则文档详细解释了签名;如何阅读、调整和创建它们。

一个规则/签名由以下部分组成:

  • 动作,决定规则匹配时会发生什么。

  • 头部,定义协议、IP地址、端口和规则的方向。

  • 规则选项,定义规则的具体内容。

以下是一个规则的示例:

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;)

在这个示例中,红色 是动作, 绿色 是头部,蓝色 是选项。

我们将使用上述签名作为本节示例,突出签名的不同部分。

10.1.1. 动作

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

更多信息请参见 动作顺序

10.1.2. 协议

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;)

签名中的这个关键字告诉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流量时匹配。

10.1.3. 源和目标

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;)

第一个突出部分是流量源,第二个是流量目标(注意方向箭头的方向)。

通过源和目标,您可以分别指定流量的来源和目的地。您可以分配IP地址(支持IPv4和IPv6)和IP范围。这些可以与操作符结合使用:

操作符

描述

../..

IP范围(CIDR表示法)

!

例外/否定

[.., ..]

分组

通常,您还会使用变量,如 $HOME_NET$EXTERNAL_NET。suricata.yaml配置文件指定了这些变量涉及的IP地址。相应的 $HOME_NET$EXTERNAL_NET 设置将替换规则中的变量。

更多信息请参见 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.srcip.dst 关键字匹配(参见 ipaddr)。这些关键字通常与数据集功能一起使用(参见 datasets)。

10.1.4. 端口(源和目标)

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;)

第一个突出部分是源端口,第二个是目标端口(注意方向箭头的方向)。

流量通过端口进出。不同的协议有不同的端口号。例如,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

[.., [..,..]]

10.1.5. 方向

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;)

方向箭头指示签名将被评估的方向。在大多数签名中,使用向右的箭头(->)。这意味着只有具有相同方向的数据包才能匹配。 还有双箭头(=>),它像 -> 一样尊重方向性,但允许匹配双向事务,与匹配每个方向的关键字一起使用。 最后,也可以让规则匹配任一方向(<>)::

source -> destination source => destination source <> destination (任一方向)

以下示例说明了方向。在这个示例中,有一个IP地址为1.2.3.4的客户端使用端口1024。一个IP地址为5.6.7.8的服务器监听端口80(通常是HTTP)。客户端向服务器发送消息,服务器回复其答案。

../_images/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

没有“反向”风格的方向,即没有 <-

10.1.5.1. 事务性规则

以下是一个事务性规则的示例:

alert http any any => 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同时获取请求和响应时才会匹配。

事务性规则可以使用方向模糊的关键字,通过指定方向。

alert http any any => 5.6.7.8 80 (msg:"matching json to server and xml to client"; sid: 1; http.content_type: to_server; content: "json"; http.content_type: to_client; content: "xml";)

事务性规则有一些限制:

  • 它们不能使用方向模糊的关键字。

  • 它们仅适用于首先向服务器发送请求,然后向客户端发送响应的事务,而不是相反(未经测试)。

  • 如果它们还在服务器方向上有流缓冲区,则不能有 fast_patternprefilter 到客户端方向,参见下面的示例。

  • 如果单个方向性规则足够,它们将拒绝加载。

此规则不能有 fast_pattern 到客户端,因为 file.data 是一个流缓冲区,并且会拒绝加载。

alert http any any => any any (file.data: to_server; content: "123"; http.stat_code; content: "500"; fast_patten;)

如果没有明确指定,事务性规则将默认选择服务器方向的 fast_pattern

10.1.6. 规则选项

规则的其余部分由选项组成。这些选项用括号括起来,并用分号分隔。一些选项有设置(如 msg),由选项的关键字后跟冒号和设置指定。其他选项没有设置;它们只是关键字(如 nocase)::

<关键字>: <设置>; <关键字>;

规则选项有特定的顺序,改变它们的顺序会改变规则的含义。

Note

字符 ;" 在Suricata规则语言中有特殊含义,必须在规则选项值中转义。例如::

msg:"Message with semicolon;";

因此,您还必须转义反斜杠,因为它作为转义字符。

本文档的其余部分记录了各种关键字的使用。

以下是一些关于关键字的通用细节。

10.1.6.1. 禁用警报

有一种方法可以使用关键字 noalert 禁用规则的警报生成。当此关键字是规则的一部分时,如果规则的其他部分匹配,则不会生成警报。也就是说,其他规则动作 仍将被应用。使用 noalert 可以帮助规则使用 flowbitsdatasets 或其他规则语言的状态维护构造来收集或设置状态。参见 阈值设置关键词 了解其他控制警报频率的方法。

以下规则展示了 noalert 的熟悉模式:

  • 第一条规则标记状态而不生成警报。

  • 第二条规则如果状态已设置且满足其他条件,则生成警报。

alert http any any -> $HOME_NET any (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; )

alert http any any -> $HOME_NET any (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请求。

drop tcp any any -> any 22 (msg:"Drop inbound SSH traffic"; noalert; sid: 3)

10.1.6.2. 修饰关键字

一些关键字作为修饰符。有两种类型的修饰符。

  • 较旧风格的 '内容修饰符' 会回溯规则,例如::

    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 关键字之后。

10.1.6.3. 规范化缓冲区

数据包由原始数据组成。HTTP和重组会复制这些类型的数据包数据。它们会消除异常内容,合并数据包等。剩下的被称为“规范化缓冲区”:

../_images/normalization1.png

因为数据被规范化,所以它不再是原来的样子;它是一种解释。规范化缓冲区包括:所有HTTP关键字、重组流、TLS、SSL、SSH、FTP和dcerpc缓冲区。

请注意,有一些例外,例如 http_raw_uri 关键字。更多信息请参见 http.uri