能解释 HTTP 归一化缓冲区的作用,并用 http_uri、http_header、http_method 等关键字检测 Web 攻击。
上一课结束时,你的规则已经能从授权靶场 PCAP 里精确命中目标攻击流,对背景流量零误报——只是那套规则靠 content 与 pcre 在原始载荷里找特征串。HTTP 是 Web 攻击的主战场:SQL 注入、路径穿越、命令注入,大多藏在请求的方法、URI 和请求头里。现在把匹配范围从整包载荷收窄到 HTTP 字段。
规则是给 Suricata 的指令:找什么流量,命中后做什么。同样的特征串,放在正确的字段缓冲区里,比满载荷匹配更准;放错地方,要么漏报,要么告警疲劳。规则头协议字段写 http,HTTP 缓冲区关键字才会参与匹配。
下面聚焦四个字段关键字:http_uri、http_method、http_header、http_stat_code。
核心概念
HTTP 归一化缓冲区
生活类比:快递分拣中心不会拿包裹上五花八门的地址写法直接比对,而是先把地址统一成标准格式,再按快递单找件。Suricata 处理 HTTP 也一样:先把请求拆成字段——方法、URI、请求头、状态码、正文——再把字段归一化,规则匹配发生在归一化后的字段上,而不是原始报文字节上。
技术定义:HTTP 缓冲区关键字把 content 等匹配限制到 HTTP 消息中某个解析后的字段。Suricata 规则文档把这类关键字归为归一化缓冲区(Normalized Buffers):引擎先解码并整理字段内容,规则再在其上匹配。http_uri 匹配归一化后的 URI,http_method 匹配请求方法,http_header 匹配请求头,http_stat_code 匹配响应状态码。
归一化的价值在防绕过。URI 归一化会把百分号编码还原,比如 %2e 还原为 .。攻击者用编码变换躲纯字节匹配时,归一化缓冲区仍能命中,漏报因此降低。需要精确的原始字节时,可改用对应的原始缓冲区(Raw Buffer),相关关键字列在规则文档的 HTTP Keywords 章节。
http_uri 匹配归一化后的 URI。下面这条规则同时演示 http_method 与 http_uri:
alert http any any -> any any (msg:"SQL 注入尝试:URI 含 union 与 select"; http_method; content:"GET"; http_uri; content:"union"; nocase; http_uri; content:"select"; nocase; classtype:web-application-attack; sid:1000001; rev:1;)http_method 把 content:"GET" 限定在请求方法上;http_uri 把 content:"union" 与 content:"select" 限定在 URI 上。请求行之外的字节不参与这两处匹配。payload 出现在 Cookie 或正文里时,这条规则不会触发。对比之下,纯 content 匹配整包载荷,任何字段都可能命中,误报面大得多。content 的修饰符(nocase、depth、distance)在字段缓冲区内照常生效,只是匹配起点被锁在字段内。
归一化还带来抗绕过能力。攻击者常把 . 编码成 %2e,骗过基于原始字节的规则。URI 先解码再匹配,http_uri;content:"/../" 依然能命中这类路径穿越请求。部分旧文档与规则集把同一关键字写作 uricontent,它匹配的同样是归一化后的 URI 内容。
http_header 匹配请求头。扫描器指纹常藏在 User-Agent 里:
alert http any any -> any any (msg:"可疑 User-Agent"; http_header; content:"sqlmap"; nocase; classtype:web-application-attack; sid:1000002; rev:1;)匹配只在请求头里进行;正文里出现 sqlmap 字样不会触发这条规则。攻击者把 payload 写进别的头字段时,这条规则同样保持安静——字段缓冲区的作用就是让规则只回答它该回答的问题。
响应侧用 http_stat_code 匹配状态码。持续 500 往往意味着攻击在目标上生效:
alert http any any <> any any (msg:"HTTP 500 响应"; http_stat_code; content:"500"; sid:1000003; rev:1;)http_stat_code 是响应字段,箭头方向必须覆盖服务器到客户端。<> 表示方向无关,适合这类请求与响应都要看的场景。
本课回放只使用本地 PCAP 与授权靶场流量。从授权场景提取特征后,先在本地回放验证,再决定是否部署。不要对未授权的真实目标抓包或测试——越权验证本身就是违规行为。规则质量差会导致漏报与告警疲劳,越权测试则直接越过了防御边界,两者都要避免。
动手:验证 HTTP 缓冲区规则
- 1
打开默认规则文件,准备追加新规则。该路径是 suricata-update 安装规则的默认位置;你的环境若不同,沿用前几课实际使用的规则文件。
bashsudo vim /var/lib/suricata/rules/suricata.rules - 2
追加三条规则:SQL 注入(http_method + http_uri)、可疑 User-Agent(http_header)、500 响应(http_stat_code)。
suricataalert http any any -> any any (msg:"SQL 注入尝试:URI 含 union 与 select"; http_method; content:"GET"; http_uri; content:"union"; nocase; http_uri; content:"select"; nocase; classtype:web-application-attack; sid:1000001; rev:1;) alert http any any -> any any (msg:"可疑 User-Agent"; http_header; content:"sqlmap"; nocase; classtype:web-application-attack; sid:1000002; rev:1;) alert http any any <> any any (msg:"HTTP 500 响应"; http_stat_code; content:"500"; sid:1000003; rev:1;) - 3
运行第 1 章学过的测试模式(-T)校验该规则文件,确认无语法错误。
- 4
离线回放一个包含 HTTP 流量的授权 PCAP。核心形式如下,其余参数沿用你第 1 章 -r 回放的完整写法。
bashsudo suricata -r path-to-pcap - 5
查看 fast.log,确认告警出现。
bashsudo tail -n 50 /var/log/suricata/fast.log
你应该看到
测试模式无语法错误。回放后 fast.log 中出现 sid 1000001 与 1000002 的告警(前提是 PCAP 里确实存在对应特征);若回放流量含 500 响应,1000003 也会出现。eve.json 中能看到这些告警事件(查看方法同第 1 章)。某条未命中时,先回 PCAP 确认特征真实存在,再对照下面的 troubleshoot 排查。
遇到问题:回放授权 PCAP 后,fast.log 里没有出现预期告警。
可能原因
- PCAP 里根本没有这条特征:URI 不含 union/select,或 User-Agent 不是 sqlmap。
- 特征在别的字段:payload 写在正文或 Cookie 里,http_uri、http_header 不会命中。
- 方向不对:http_stat_code 是响应字段,单向箭头若只覆盖客户端到服务器方向就会漏掉。
- 规则文件没被加载:文件路径与 suricata.yaml 引用不一致,或测试模式没有包含该文件。
- fast.log 未启用:suricata.yaml 里没有打开 fast.log 输出。
排查步骤
- 用 Wireshark 打开 PCAP,先按 http 过滤,确认特征确实存在于目标字段。
- 把字段缓冲区关键字临时换成 content 做对照实验:若 content 命中而 http_uri 不命中,说明缓冲区选错了。
- 核对方向:请求字段用客户端到服务器方向;响应字段覆盖服务器到客户端方向,或直接用 <>。
- 用测试模式确认规则文件被加载且无语法错误。
- 确认 suricata.yaml 启用了 fast.log 输出,回放后再 tail fast.log 检查。
- 换更长或更独特的特征串,排除误匹配与截断因素。
自检:为什么 http_uri;content:"/../" 能命中把点号编码成 %2e 的路径穿越请求,而纯 content 匹配同一报文却可能漏报?
http_uri 是归一化缓冲区:Suricata 先把 URI 百分号解码(%2e 还原为 .),再在归一化后的字段上匹配,因此能命中解码后的 /../。纯 content 匹配原始字节,报文里实际是 %2e%2e 的字节序列,找不到 /../ 字面串,于是漏报。这正是归一化缓冲区降低编码绕过漏报的原理。