修订记录
版本 | 日期 | 修订人 | 备注 |
---|---|---|---|
1.0 | 2023.04.24 | 魔神8号 | 初始版本 |
1.1 | 2023.05.18 | 魔神8号 | 完善和扩充部分语法说明 |
说明
- 这篇文档来自于对snort3官方文档的解读,并结合了一些实际的验证。基于snort版本
3.1.59.0
。 - 目前本文档还不是最终的完成状态,部分语法存在缺失或一带而过(大概涵盖完整语法的70%左右)。
1 规则集
Snort 规则分为两组:"社区规则集"和"Snort 订阅者规则集"。 Snort 订阅者规则集由 Cisco Talos 开发、测试和批准。Snort 订阅者规则集的订阅者将在规则集发布给思科客户时实时收到规则集。您可以通过 Snort.org 网站下载规则并将它们部署到您的网络中。社区规则集由 Snort 社区开发,并由 Cisco Talos 进行 QA(质量保证,Quality Assurance)。它免费提供给所有用户。
订阅者规则集介绍:www.snort.org/products
规则集下载:www.snort.org/downloads/#...
:::info 说明:
Cisco Talos是思科公司旗下的一个网络安全研究团队,专注于网络安全威胁研究、恶意代码分析和网络威胁情报收集等方面。Cisco Talos的研究成果和威胁情报数据被广泛应用于思科的安全产品和服务中,以提供更加全面和高效的安全保护。 :::
2 VS Code 插件
VS Code 可以安装snort插件,以支持snort规则语法高亮,方便阅读和编写snort规则(某些snort3语法不一定支持高亮)。
3 语法规范
3.1 基本信息
规则文件 :规则文件是规则的载体,以 .rules
作为文件后缀。
3.1.1 注释
单行注释
c
# 这是单行注释。遇到换行结束
多行注释
c
#begin....
这是多行注释
这是多行注释
#end... 截止到换行
C风格多行注释
c
/*
这是多行注释
这是多行注释
*/
注意:
- 注释不要遗漏 #end ,否则会导致规则#begin 之后的规则失效,而且加载时不会有错误提示!
3.1.2 总体结构
c
1 2 3 4 5 6
______ _____ _________ ___ _________ _____________________
ACTION PROTO SIP SPORT DIR DIP DPORT ( OPTION1; OPTION2; ... )
|---------- header -----------------|(--------- body --------)
c
alert udp any any <> any 53
(
msg: "alert dns 'content' test";
sid: 1;
content : "|05|baidu|03|com", nocase, offset 12, depth 10;
)
规则头:包含流量匹配后的动作 ,流量的协议 、IP地址 、端口 、方向。
规则体 :诸多选项 组成。主要是定义规则匹配所需的有效负载和非有效负载标准。
3.2 规则头
一个传统的规则头由五个主要部分组成:
- 动作:规则命中时要执行的动作。
- 协议:流量使用哪个协议。
- IP地址:流量的网络地址。
- 端口:流量的端口。
- 方向(操作符):流量方向。
:::warning 注意:
Snort 3 还引入了三种新的规则类型,每种规则类型都有自己的规则头格式,这三种规则类型将在后面的章节中进行介绍。 :::
3.2.1 动作
动作 | 优先级 | 说明 | 备注 | ||
---|---|---|---|---|---|
1 | alert | 20 | 针对当前数据包生成警报 | 基本动作 | |
2 | block | 50 | 阻止当前数据包和此流的所有后续数据包(有警报) | ||
3 | drop | 40 | 丢弃当前数据包(有警报) | ||
4 | log | 10 | 记录当前数据包到日志文件 (无警报,u2模式有日志) | ||
5 | pass | 70 | 仅将当前数据包标记为已通过 (无警报,u2模式无日志) | ||
6 | react | drop + 1 | 向客户端发送响应并终止会话(有警报,如发送http 403 Forbidden 页面) |
主动响应。它们执行某些操作以响应检测到的数据包 | |
7 | reject | 60 | 使用 TCP reset(TCP流量) 或 ICMP unreachable(UDP流量)终止会话 | ||
8 | rewrite | 30 | 根据规则中的"替换"选项启用覆盖数据包内容 |
上述优先级见 src/framework/ips_action.h
。
疑问: 当同一数据包命中不同action时,较高优先级action会覆盖较低先级的action,还是按优先级顺序来执行action?
3.2.2 协议
3.2.2.1 普通协议
协议 | 说明 | |
---|---|---|
1 | ip | OSI第3层 |
2 | icmp | OSI第3层 |
3 | tcp | OSI第4层 |
4 | udp | OSI第4层 |
5 | 应用层协议/服务 | 见下文 |
3.2.2.2 应用层协议/服务
The names of services that can be used here can be found by looking at the wizard entries in the snort_defauls.lua file included in the lua/ directory, as well as the curse service names present in the curse_map in src/service_inspectors/wizard/curses.cc.
上述文档中说可用的应用层协议/服务 可以在 lua/snort_defauls.lua 中的wizard 条目和 src/service_inspectors/wizard/curses.c 中的curse_map 中查看。(此处应该是笔误:snort_defauls.lua -> snort_defaults.lua)
巫师使用巫术、咒语和诅咒来确定流程中最有可能的服务。它不能确定服务,其目标是让最有可能的服务检测器尽快参与进来。 wizard:巫师。这里是一种比喻性的说法,用来描述协议识别使用的技术和方法。 hex:巫术。基于十六进制进行模式匹配。 spell:咒语/符咒。基于文本的模式匹配。 curse:诅咒。协议/服务识别的内部算法。它们在 C++ 代码中作为状态机实现,并且可以在流中存储自己唯一的状态信息。
服务列表:
序号 | 应用层协议/服务 | 备注 |
---|---|---|
1 | ftp | spell |
2 | http | |
3 | imap | |
4 | pop3 | |
5 | smtp | |
6 | sip | |
7 | ssh | |
8 | dce_http_server | |
9 | dce_http_proxy | |
10 | dnp3 | hexes |
11 | netflow | |
12 | http2 | |
13 | ssl | |
14 | telnet | |
15 | dce_udp | curses |
16 | dce_tcp | |
17 | dce_smb | |
18 | mms | |
19 | s7commplus | |
20 | sslv2 |
:::warning 备注:
- 按照目前对官网文档的理解,snort3中服务 应该和应用层协议是等效的。 :::
3.2.3 IP地址
序号 | 格式 | 说明 | 示例 |
---|---|---|---|
1 | 单个CIDR | 如192.168.0.5、192.168.1.0/24 | |
2 | 变量 | 配置文件中定义 | <math xmlns="http://www.w3.org/1998/Math/MathML"> E X T E R N A L N E T 、 EXTERNAL_NET 、 </math>EXTERNALNET、HOME_NET |
3 | any | 表示任意IP地址 | |
4 | 列表 | [item1,item2,...],括在方括号中并用逗号分隔。 | [192.168.1.0/24,10.1.1.0/24] |
5 | ! | 排除。可于其他格式组合使用(与any组合暂未验证) | !192.168.1.1 、![192.168.1.1,192.168.1.2] |
:::info 注意:
不知是语法不完备或第对规范理解上的问题。192.168.1.1,192.168.1.2 和 [192.168.1.1,192.168.1.2] 似乎是等效的。 :::
3.2.4 端口号
序号 | 类型 | 说明 | 示例 |
---|---|---|---|
1 | 静态端口 | 单个端口号 | 如80 、443 |
2 | 端口变量 | 配置文件中指定 | $HTTP_PORTS |
3 | 端口段/区间 | 使用范围运算符(':')指示。闭区间 | 1:1024、500: |
4 | 端口列表 | 括在方括号中并用逗号分隔 | [1:1024,4444,5555,$HTTP_PORTS] |
5 | any |
:::success 注意 :
如果规则体 中指定了service 选项,则规则头中的端口不必与流量中的端口匹配。具体见 service 相关章节。 :::
3.2.5 方向运算符
序号 | 方向运算符 | 说明 |
---|---|---|
1 | -> | 左为源,右为目的 |
2 | <> | 双向运算符。不区分方向 |
3.3 新规则类型(snort3)
snort3 版本中增加了三种新的规则类型来简化和增强规则编写。
序号 | 规则类型 | 语法 | 说明 | 备注 |
---|---|---|---|---|
1 | 服务规则 | ACTION SERVICE (BODY ) |
规则头中仅包含动作 和应用层协议。 | |
2 | 文件规则 | ACTION file (BODY ) |
匹配特定文件,而不关注协议。 | |
3 | 文件识别规则 | file_id (BODY ) |
使用新规则选项file_meta 来执行文件类型识别 |
3.3.1 服务规则(service rule)
c
ACTION SERVICE (BODY) == ACTION PROTO any any <> any any (BODY)
示例
c
alert http
(
msg:"SERVER-WEBAPP This rule only looks at HTTP traffic";
flow:to_server,established;
http_uri;
content:"/admin.php",fast_pattern,nocase;
content:"cmd=",nocase;
pcre:"/[?&]cmd=[^&]*?\x3b/i";
sid:1;
)
:::success 注意 :
如果规则头中已经指定了服务 或在创建文件规则时**,规则体中不应**使用 service 选项。(实际验证当指定了service选项时,并不会生效) :::
3.3.2 文件规则(file rule, TODO)
文件规则可用于匹配特定文件。目前支持以下任何应用层协议输出的文件:
- HTTP
- SMTP
- POP3
- IMAP
- SMB
- FTP
示例
c
alert file
(
msg:"alert file test";
sid: 778;
file_data;content:"This program cannot";
)
:::info 注意:
针对文件规则,规则编写者应确保做到如下两件事
-
使用file_data选项修饰文件中应匹配的内容
-
规则中省略规则选项service、flow
(实际验证service 选项依旧有效) :::
3.3.3 文件识别规则(TODO)
文件识别规则利用 Snort 的检测引擎来启用文件类型识别。这些规则是基本的 Snort 3 规则,但它们不是警告和/或阻止流量,而是根据文件的内容识别文件,然后定义可在带有file_type选项的后续规则中使用的文件类型。
:::info TODO:
规则语法解读
与文件规则的区别 :::
3.4 规则体
规则体由规则选项组成。规则选项是 Snort 规则的核心。
每个规则选项都有自己的规范,但是都遵会循相同的一般结构:
- 规则选项包含在规则头之后的括号中
- 规则选项由一般由选项名 和选项参数 组成
- 选项名 和参数直接通过冒号 分隔。如
service: http;
。 - 参数和参数之间通过逗号 分隔。如
service: http, https;
。 - 参数和参数的参数直接通过空格 分隔。如
content : "|05|baidU", nocase, offset 12, depth 6
;。
- 选项名 和参数直接通过冒号 分隔。如
- 规则选项以分号结束
规则选项有四大类:
- general:通用选项。为给定规则提供额外的上下文。
(2.9用户手册)选项提供有关规则的信息,但在检测过程中没有任何影响。
- payload:载荷选项。设置特定有效载荷的标准。
(2.9用户手册)这些选项都在数据包有效载荷内寻找数据,并且可以相互关联
- non-payload:非载荷选项。选项设置非有效载荷特定标准。
(2.9用户手册)这些选项寻找非有效载荷数据
- post-detection:检后选项, 设置规则"触发"后对给定数据包采取的操作(TODO)
3.4.1 通用选项(general)
速查表
序号 | 选项名 | 说明 | |
---|---|---|---|
1 | msg | 命中规则时消息输出 | |
2 | reference | 以指向相关攻击识别系统的链接的形式为规则提供额外的上下文 | |
3 | gid | 至少生成事件的** Snort 组件**。generator id | 如文件gid为规则1, http检测模块为119 |
4 | sid | 规则唯一签名编号。即签名id。 | |
5 | rev | 规则的修订版本号 | |
6 | classtype | 为规则分配类别,以指示攻击类型 | |
7 | priority | 规则的严重性别 | 可用于区分重要紧急程度(如高危、中危、低危) |
8 | metadata | 规则元数据。以name-value对的形式指定规则额外的任意信息 | 比如作者、日期等。可以提供更多的信息帮助用户理解规则的作用。 |
9 | service | 设置与给定规则关联的服务列表 | 影响检测行为 |
10 | rem | 注释信息(remark) | 以提高规则的可读性、可维护性 |
11 | file_meta | 为文件标识规则设置文件元数据 | TODO |
3.4.1.1 msg
命中时的消息输出。
- 参数类型:字符串
- 参数数量:1
- 示例:
msg:"alert dns test";
:::warning 注意 :Snort 规则有一些保留字符(例如'"'和';'),规则编写者必须将它们转义\以在msg选项中使用它们。 :::
3.4.1.2 reference
以指向相关攻击识别系统的链接的形式为规则提供额外的上下文。
- 参数类型:非字符串
- 参数数量:2
- scheme:被引用的攻击识别系统。如 cve。
- id:它是该系统内的特定标识符
示例
c
reference:cve,2000-0138;
# CVE 是通用漏洞披露(Common Vulnerabilities and Exposures)列出了已公开披露的各种计算机安全缺陷。
# 人们提到 CVE,指的都是已分配 CVE ID 编号的安全缺陷(https://www.redhat.com/zh/topics/security/what-is-cve)
3.4.1.3 gid(生成器id)
生成事件的特定** Snort 组件**。generator id。用于标识哪个组件命中的规则。
- 参数类型:正整数,>=1
- 参数数量:1
gid | 说明 | 备注 |
---|---|---|
1 | 文本规则 | 默认值 |
3 | 共享对象(so) | 待确认 |
1XX | 内置规则 | |
查看snort包含的gid
bash
$ snort --list-gids
...
116: mpls
116: pgm
116: pppoe
116: tcp
116: udp
116: vlan
119: http_inspect
121: http2_inspect
122: port_scan
123: stream_ip
124: smtp
125: ftp_server
...
3.4.1.4 sid
规则唯一签名编号。即签名id。唯一标识的Snort 规则。
- 参数类型:整数,>=1
- 参数数量:1
- 缺省值:0
:::success 备注 :
根据对snort内部规则和规则解析过程判断,sid应在同一个gid下保证唯一。即 gid+sid确定唯一的规则。 :::
Snort在规则解析过程中会尝试对规则进行去重,这可能会导致某些场景下有写规则失效。
sid+gid场景处理:
gid | sid | 协议 | 动作 | 修订版本 | 结果 | 备注 | |
---|---|---|---|---|---|---|---|
1 | 相同 | 相同 | 不同 | ------ | ------ | 错误 | |
2 | 相同 | 相同 | 相同 | 不同 | ------ | 错误 | |
3 | 相同 | 相同 | 相同 | 相同 | 不同 | 警告,保留版本较高的一条规则 | 需指定命令行选项 `--warn-all |
4 | 相同 | 相同 | 相同 | 相同 | 相同 | 警告,保留最后一条规则 |
:::warning 备注
- Snort"保留"sid值 0-999999,因为这些值用于 Snort 分发包中包含的规则。因此,用户应该使用sid从 1000000 开始的本地规则值。
- Snort 建议每条规则都要包含sid选项,虽然语法上并没有做限制。其缺省值为0(主动写入规则中的sid必须>0)。 :::
3.4.1.5 rev
规则的修订版本号。
3.4.1.6 classtype(TODO)
为规则分配类别,以指示攻击类型。
Snort 提供了一个默认分类列表,规则编写者可以使用它来更好地组织规则事件数据。
TODO
Snort 提供的攻击分类见snort_defaults.lua 中 default_classifications。
3.4.1.7 priority
规则优先级,指示重要程度。
- 参数类型:整数。1-2147483647。1最严重,2147483647 最不严重。
- 参数数量:1
虽然内置分类集classtype有自己的优先级,但规则编写者可以使用该priority选项覆盖它们。
3.4.1.8 metadata
规则元数据。以name-value对的形式指定规则额外的任意信息。
- 参数类型:键值对。空格分隔。
- 参数数量:多个。以逗号分隔。
3.4.1.9 service(重要)
设置与给定规则关联的**服务列表,**指示规则适用的服务(服务列表见3.2.2章节)
- 参数个数:1个或多个,逗号分隔。表示命中其中任意一服务即可。
c
service: http, https;
使用了此规则选项, 只要端口匹配,指定的服务就不必与流量的实际服务匹配; 只要服务匹配,端口就不必与流量的实际端口匹配; 总的来说,服务选项可以被视为一个"OR ports"语句 ,因为它允许基于端口或服务进行匹配,只要其中之一与规则选项中指定的值匹配即可。
如果在规则头 中指定了服务 或是在文件规则中,规则体中不应使用service选项。
上面的表述是清晰的,但实际验证效果可能并不完全符合预期。
这里通过dns示例进行说明。
dns示例报文:10.0.2.15 58886 udp 172.16.11.222 53
- 规则头指定了端口,规则体中指定了service选项(存在不合符预期的场景)
c
# 可命中
alert udp any any <> any 533 # 端口和样例报文不一致
(
msg:"alert dns test";
sid: 778;
service: dns; # 应用层协议与样例报文一致
)
# 未命中,不符合预期。
alert udp any any <> any 53 # 端口和样例报文一致
(
msg:"alert dns test";
sid: 778;
service: dnp3; # 应用层协议和样例报文不一致
)
- 规则头指定了服务和端口,规则体未指定service选项。需同时满足dns协议和端口。即匹配端口为53的dns流量。
c
# 可命中
alert dns any 53 <> any any # 端口和样例一致
(
msg:"alert dns test";
sid: 778;
)
- (反例)
规则头指定了服务,同时规则体指定service选项。需同时满足dns和端口,即端口是53的dns流量。
c
# 可命中,没有参考价值,不是推荐写法。
alert dns any 53 <> any any # 端口53有效
(
msg:"alert dns test";
sid: 778;
service: http; # 应用层协议和样例报文不一致
)
- (反例)
服务规则中指定了service选项
c
# 可命中,没有参考价值,不是推荐写法。
alert dns # 服务规则仅 action 和 协议
(
msg:"alert dns test";
sid: 778;
service: http; # 应用层协议和样例报文不一致
)
3.4.1.10 rem(注释)
3.4.1.11 file_meta(TODO)
规则file_meta选项为文件标识规则设置文件元数据。此选项设置将匹配的文件的类型名称、数字 id 值、类别、组和版本。
必选参数
- type
- id
可选参数
3.4.2 载荷选项
一条Snort 规则可以包含多个选项,这些选项将按照它们在规则中的顺序(某些fast_pattern匹配除外)根据数据包数据进行评估。
3.4.2.1 content
格式: :::info content:[!]"content_string", content_modifer [content_modifer_argument] :::
内容修饰符:
内容修饰符 | 说明 | 取值范围 | 备注 | |
---|---|---|---|---|
1 | nocase | 忽略大小写。默认大小写敏感 | ||
2 | offset | 起始偏移。默认0 | [-65535, 65535] | 模式串出现的区间 [offset , offset + depth] |
3 | depth | offset之后查找的范围 | [模式串长度, 65535] | |
4 | distance | 相对前一个模式串结尾处的偏移。类似offset。默认0 | ||
5 | within | distance之后差查找范围。类似depth。 | [模式串长度, 65535] | |
6 | fast_pattern | TODO |
:::info 备注:
- 内容中出现分号(;)和双引号(")字符必须转义(使用"\)或以十六进制编码。
- offset 并不是限制内容一定在出现offset处,而是给定了一个区间的起始位置。
- nocase 适用于十六进字节。如
content:"|41|",nocase;
将会查找"A"或"a"。 :::
示例:
c
# 示例报文中域名:\x05baidu\x03com
alert udp any any <> any 53 # 1. 匹配端口是53的udp流量
(
msg: "alert dns test";
sid: 1;
content : "|05|baidU", nocase, offset 12, depth 6; # 2. 从载荷偏移12字节之后的6字节中匹配 "x05baidu",忽略大小写
content : "com", distance 1, within 3; # 3. 从"\05baidu"尾部偏移1之后的3个字节中匹配 "com"
)
3.4.2.2 bufferlen
用于检查给定缓冲区长度。每条规则最多一条。取值范围 [0, 65535]。
语法:
bufferlen:[<|>|=|!|<=|>=]length[,relative]; bufferlen:min_length{<>|<=>}max_length[,relative];
符号 | 说明 | ||
---|---|---|---|
1 | 大于 | 单值比较 | |
2 | >= | 大于等于 | |
3 | < | 小于 | |
4 | <= | 小于等于 | |
5 | = 或省略 | 等于 | |
6 | ! | 不等于 | |
7 | <> | 区间,不包含边界值 | 范围比较 |
8 | <=> | 区间,包含边界值 |
如果添加relative
关键字修改,表示相对于检测光标/检测位置,剩余buffer的长度。
示例
c
# 示例报文中域名:\x05baidu\x03com,udp载荷长度38个字节
alert udp any any <> any 53 # 1. 匹配端口是53的udp流量
(
msg: "alert dns 'bufferlen' test1";
sid: 2;
content : "|05|baidU", nocase, offset 12, depth 6; # 2. 从载荷偏移12字节之后的6字节中匹配 "\05baidu",忽略大小写
# bufferlen : 20, relative; # 3. 此处检测光标偏移为16个字节,38-18=20。与depth等无关。
content : "com", distance 1, within 3;
# bufferlen : 16, relative; # 4. 此处检测光标偏移为22个字节,38-22=16
# bufferlen : 38; # 5. 包长/检测缓存区长度为38个字节
)
# 配合http粘性缓冲区,可用于检查http特定字段的长度(无relative时未验证)
alert http
(
msg:"alert http c2s bufferlen test";
http_method; content:"GET"; # 方法为GET时,method缓冲区长度必然为3个字节
bufferlen:0, relative; # 从method缓冲区中测完"GET"后,其剩余0个字节
sid: 206;
)
alert http
(
msg:"alert http c2s bufferlen test";
http_method; content:"GE"; # 方法为GET时,method缓冲区长度必然为3个字节
bufferlen:1, relative; # 从method缓冲区中测完"GE"后,其剩余1个字节
sid: 206;
)
3.4.2.3 isdataat(TODO)
3.4.2.4 dsize(TODO)
存疑。
dsize选项用于测试数据包的有效负载大小。
语法上和 bufferlen类似。
dsize:[<|>|=|!|<=|>=]size; dsize:min_size{<>|<=>}max_size;
3.4.2.5 pcre
用于创建 perl 兼容的正则表达式。
pcre 正则语法可参考 pcrepattern man page。
语法:
pcre:[!]"/pcre_string/[flag...]";
flag | 说明 | |
---|---|---|
1 | i | 不区分大小写 |
2 | s | . 元字符支持匹配换行符 |
3 | m | 多行匹配。默认情况'^' 和 ''仅匹配字符串的开头和结尾。<br />设置时m后,'^' 和 '' 匹配缓冲区中任何换行符之后或之前的紧跟位置,以及缓冲区的开头和结尾。 |
4 | x | 指定忽略模式中的空白数据字符,除非转义或在字符类中 。TODO |
5 | A | 指定模式必须仅在缓冲区的开头匹配(与指定 '^' 字符相同) |
6 | E | 将"$"设置为仅匹配主题字符串的末尾 |
7 | G | 反转量词的"贪婪",使它们在默认情况下不贪婪,但如果后跟 '?' 则变得贪婪。 |
8 | O | 覆盖为此表达式配置的 pcre 匹配限制和 pcre 匹配限制递归。TODO |
9 | R | 从最后一此匹配结束而不是从缓冲区开始开始正则表达式搜索。TODO |
示例
c
alert udp any any <> any 53
(
msg: "alert dns 'pcre' test";
sid: 2;
pcre : "/^.{12}\x05baidU/i";
content : "com", distance 1, within 3;
pcre : "/\x00\x00\x29\x02\00\x00/";
)
3.4.2.5 regex(TODO)
用于创建 perl 兼容的正则表达式,使用安装 hyperscan,并在配置文件中启用。
3.4.2.6 http 特定选项
snort3中,HTTP检测器(HTTP inspector)会将http数据解析为不同元素 (e.g., URIs, headers, methods, etc.),并放入各个粘性缓冲区中。
如下是一个反例。
c
alert http
(
msg:"alert http c2s bufferlen test";
content:"GET"; # 没有http粘性缓冲区选项,内容匹配会不命中。
content:"Host";
sid: 206;
)
http 粘性缓冲区应放在内容匹配选项之前。 粘性缓冲区之后可以跟多个content。
c
[sticky buffer]; content:"xxx";
示例
c
alert http
(
msg:"alert http c2s bufferlen test";
http_method; pcre:"/GE/";
content:"T"; # 在http_method中查询
http_header:field host;content:"172.16";
content:"11.100"; # 在host 字段中查询
sid: 206;
)
:::warning 说明:
- 实际验证,在使用了 http 选项时,应同时使用 service 选项,即
service: http;
(规则头中服务为http时除外) - 如遗漏service选项,实际上snort3内部也会自动添加对应选项。 使能
--warn-all
时,会抛出相应的警告。 :::
3.4.2.6.1 http_uri 和 http_raw_uri
这2个选项表示从HTTP 请求 URI 中查找数据。
http_uri缓冲区包含 **完整的 规范化 **URI,而http_raw_uri缓冲区包含 完整的 未规范化 的URI。
Snort 在解析 HTTP 请求时,会将URI中需要规范化的任何内容进行规范化,并将最终结果放入http_uri缓冲区中。
规范化操作如下:
- 解码百分比编码值(例如"%41%41"->"AA)
- 将反斜杠替换为正斜杠
- 将加号替换为空格
- 路径简化
- 等等
Snort 会将HTTP URI解析为6个单独的组件,并可以限定在这6个组件中查找数据。
- scheme
- host
- port
- path
- query
- fragment
http
GET https://www.samplehost.com:287/basic/example/of/path?with-query=value#and-fragment HTTP/1.1\r\n
scheme -> https
host -> www.samplehost.com
port -> 287
path -> /basic/example/of/path
query -> with-query=value
fragment -> #and-fragment
格式:
ini
http_uri[:{scheme|host|port|path|query|fragment}];
http_raw_uri[:{scheme|host|port|path|query|fragment}];
示例 :
未规范化URI和选项示例
http
/inc/user_count.php?date=Thu%20Apr%2013%202017%2013:48:53%20
GMT+0800%20(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9
%97%B4)
c
http_raw_uri:query; content: "Thu%20Apr%2013%202017";
规范化URI选项示例
http
/inc/user_count.php?date=Thu Apr 13 2017 13:48:53 GMT+
0800 (中国标准时间)
c
http_uri:query; content: "Thu Apr 13 2017";
3.6.2.6.2 http_method
该选项用于匹配http方法。
示例:
c
http_method; content:"POST";
3.6.2.6.2 http_header 和 http_raw_header
这2个选项表示在请求头/响应头中查找数据。
http_header 表示规范化的头部,http_raw_header表示未规范化的头部。
格式:
c
http_header[:field header_name]; # field 关键字可用于限定字段名。
http_raw_header[:field header_name];
header_name
支持的字段官网文档中并没有列出。常见的字段名如 host 、Connection等,大小写都可以。
示例:
c
http_header:field host ; content: "172.16.11.100"; # Host、HosT等都支持
http_header; content: "Host: 172.16.11.100";
3.4.3 非载荷选项
3.4.3.1 IP头部相关
3.4.3.1.1 fragoffset(IP头)
检查IP头部中IP分片偏移值。
fragoffset:[<|>|=|!|<=|>=]fragoffset; fragoffset:fragoffset_min{<>|<=>}fragoffset_max;
c
alert ip any any -> any any
(
msg: "alert ftp 'fragoffset' test";
sid: 4;
fragoffset: !0;
)
3.4.3.1.2 ttl
检查 IP 头部中的 IP 生存时间 (TTL) 值。
ttl:[<|>|=|!|<=|>=]ttl; ttl:ttl_min{<>|<=>}ttl_max;
3.4.3.2 TCP头相关
3.4.3.2.1 seq
seq:[<|>|=|!|<=|>=]seq; seq:seq_min{<>|<=>}seq_max;
3.4.3.2.2 ack
ack:[<|>|=|!|<=|>=]ack; ack:ack_min{<>|<=>}ack_max;
3.4.3.2.3 window
window:[<|>|=|!|<=|>=]window; window:window_min{<>|<=>}window_max;
3.4.3.3 flow
用于检查给定数据包的会话属性。
flow:[{established|not_established|stateless}]
[,{to_client|to_server|from_client|from_server}]
[,{no_stream|only_stream}] \ [,{no_frag|only_frag}];
参数 | 描述 | 类别 |
---|---|---|
to_client | 匹配服务器响应 | 数据包方向 |
to_server | 匹配客户端请求 | |
from_client | 匹配客户端请求 | |
from_server | 匹配服务器响应 | |
established | 仅匹配已建立的 TCP 连接 | 流状态 |
not_established | 仅在未建立 TCP 连接时匹配 | |
stateless | 忽略流状态 | |
no_stream | 仅匹配非重组数据包 | 重组? |
only_stream | 仅匹配重新组装的数据包 | |
no_frag | 仅匹配碎片数据包 | IP分片重组? |
only_frag | 仅匹配经过碎片整理的数据包 |
检测后选项(TODO)
总结
- snort规则使用轻量级语法,结构简单,语法清晰,相对容易理解
- snort规则语法丰富,功能强大
- snort引擎对规则有较为友好的语法检查和容错机制
- 存在语法错误时,解析阶段会抛出详细的提示信息,精确到行
- 使用http选项时对 service 选项遗漏提醒和自动补充
- snort3对规则语法处理上可能不够完备
- 有时遗漏 ";"不会抛出异常
- 多条distance 、 within 修饰的
content
选项组合使用时,某些情况下无法命中
- 如果期望对snort规则有较为准确和深入的理解,仅停留在文档层面是不够的,需要经过持续的实践积累,且要对snort引擎内部原理有一定了解