Snort简介
Snort是免费开源的IDS/IPS(入侵检测/防御系统)系统,于1998年开发,旨在检测和响应网络中的可疑活动。包含流量/协议分析、内容匹配等功能,并可用预定义规则检测和防止各种攻击。官方网站:https://docs.snort.org/rules/
Snort有两个主要的版本,Snort2.X和Snort 3.0。前者使用范围较广,后者则是最新版本,在效率、性能等方面有了一些改进。
部署方式如下,IPS位于防火墙后,交换机前,因为要对恶意包进行拦截。如果是IDS则可以和交换机平行部署。Snort规则与典型的防火墙规则也非常相似。
工作机制
通过上面网络基础设施,到达IDS/IPS后,Snort插件进行抓包、解码、预处理、规则检测引擎。
数据包捕获与预处理
-
数据包捕获(Packet Capture): Snort 使用 libpcap 库从网络接口捕获流量数据,将所有通过网卡的流量复制到Snort内部进行分析。Snort 在这一阶段获取所有网络数据包,不论其协议类型或端口号
-
预处理(Preprocessor): 捕获的数据包进入 Snort 之前,会经过一系列预处理插件进行数据标准化、解码或初步检测。预处理器有助于将数据标准化,以确保 Snort 后续检测和匹配的准确性,并识别一些特定类型的攻击,如分片攻击或协议模糊攻击。
常见的预处理器功能包括:
- 数据包重组:对于被分片的 IP 包,Snort 会将其重新组装成完整的包。
- 解码器:解码某些特定协议如 HTTP、DNS 等,以便进一步检测。
- TCP 流重组:跟踪 TCP 连接的状态,确保可以识别基于会话的攻击。
预处理是以插件形式进行的,一是方便了开发者制定适合自己的预处理系统,另一方面可以提供多种不同的预处理插件供用户选择。
检测引擎
检测引擎是 Snort 的核心组件,负责根据定义的规则来分析数据包,检测是否存在恶意行为。如果规则与数据包匹配成功就会产生相应的告警并记录日志。
-
规则集(Rule-Based System): Snort 的检测引擎基于一组灵活的规则。这些规则可以描述多种协议(如 TCP、UDP、ICMP 等)的攻击模式。每条规则由一个动作(如警告、记录等)、协议类型、源/目的地址、端口号,以及一系列可选的检测条件组成。
-
Snort 的检测依赖于规则库。规则库存储了大量的已知威胁模式,除了可以自定义规则,还可以采用Snort 社区和 Cisco Talos 定期更新并发布规则集。
-
规则一般定义在rules文件夹下。在Snort进行初始化配置时,会将这些规则读入内存。
Snort规则
所有的规则都可以分成两部分:规则头部和规则选项。
规则头部
Action指定了Snort检测到匹配流量时进行的操作,包含alert、log、pass、drop等。常用的是alert生成告警并记录日志。log则是只记录不生成告警。
Protocol制定了要检测的网络协议,包含:tcp、udp、icmp、ip。
IP 地址与端口:源地址和目标地址可以使用具体 IP 地址、网段或 any
来表示任意地址。端口可以指定单一端口号,或使用范围(如 1000:2000
),也可以使用 any
来匹配任意端口。Direction表示流量方向符号,->表示从源到目标的流量。
规则选项
规则选项用于进一步定义流量检测的具体条件以及触发警报时的动作。它们位于规则的圆括号内,每个选项由关键字和参数组成。常用关键字包含msg(规则匹配时生成的报警信息)、sid(唯一的规则标识符)、rev(规则版本)、content(检测数据包中的特定内容)、nocase(忽略大小写)、offset(开始搜索内容的起始位置)、depth(从起始位置起的搜索深度)、flags(tcp规则中用来匹配tcp报文的标志位SYN、ACK)、flow(指定数据包的方向和状态)、pcre(正则匹配)等。
规则库一般包含许多.rules文件。例如application.rules(应用程序检测规则)、database.rules(数据库检测规则)等。而每个rules文件则是诸多规则的合集,示例如下。
alert tcp any any -> any 80 (msg:"SQL Injection attempt detected"; content:"UNION SELECT"; nocase; http_uri; sid:1000001;)
alert tcp any any -> any 80 (msg:"Directory Traversal attempt"; content:"../"; http_uri; sid:1000002;)
alert tcp any any -> any 80 (msg:"Attempt to access /etc/passwd"; content:"/etc/passwd"; http_uri; sid:1000003;)