摘要

  • RFC 3128 把“小分片”与“重叠分片”两种已知手法组合起来,使过滤器批准的 TCP 首部与终点实际重组出的首部出现差异。
  • 修复要求零偏移 TCP 分片必须包含策略所需的完整最小首部,同时继续丢弃偏移量为一的分片。
  • 攻击效果取决于访问规则与主机的重叠处理方式;分片通过并不等于 TCP 连接完成、服务受损或所有实现都存在漏洞。

一条入站规则可能允许外部连接某个公开服务,同时禁止同一主机上的其他端口接受新连接。过滤器看见第一个 IPv4 分片时,目的端口指向允许的服务,TCP 控制字段也没有触发拒绝条件。就这份视图而言,放行没有矛盾。

RFC 3128 的关键问题是:这份视图还不是终点交给 TCP 的最终对象。

示例中的第一个分片从偏移量零开始,携带至少十六个 TCP 首部字节。它包含源端口、目的端口、序列号以及后续的关键字段,足以让过滤器把它识别为发往许可端口的新连接。

第二个分片也从零开始,却只带八个传输层字节。它覆盖源端口、目的端口和序列号,没有覆盖更靠后的 TCP 标志位。攻击者借此把目的端口改成原本只允许出站使用的端口。第三个分片再把数据报补全。如果终点的重叠规则让这八个新字节取代第一片的对应字节,那么最终首部会同时继承两个版本:端口来自短重叠片,控制字段来自先前通过检查的首片。

过滤器批准了一组字节,主机消费的却可能是另一组字节。

这套组合绕过的是 RFC 1858 的一项既有防御。RFC 1858 分别讨论了小分片攻击和重叠分片攻击。前者把策略所需的 TCP 字段拆到后续分片,后者利用不同重组器对重复区间的选择差异。它提出的“间接方法”会丢弃分片偏移量等于一的 TCP 分片。

IPv4 的偏移量以八字节为单位。偏移量一正好从最初八个 TCP 字节之后开始。阻断这一位置,可以防止一种经典做法:先发送过短的首片,再把 TCP 标志放进紧随其后的分片,让过滤器无法把端口与标志放在一起判断。

RFC 3128 发现,替换片不必从一开始。它可以重新从零开始。原来的防御盯住了“紧接首片的缺口”,却没有保证任何零偏移分片都足够长,更没有保证首部早期字节不会被另一个零偏移版本覆盖。

这不是一句“IPv4 分片很复杂”可以代替的机制。发送方控制分片边界、偏移量、到达次序与重叠内容;过滤器控制眼前视图的准入;终点 IP 栈控制重组;TCP 判断重组段是否合法;监听服务决定连接是否继续。每个角色都只控制一段,任何一段都不能独自证明最终结果。

RFC 3128 因此保留了重要限制:攻击是否成立,取决于终点“精确的分片重组实现”。RFC 791 建立了 IPv4 分片字段与重组责任,RFC 815 则展示了如何用孔洞列表处理乱序与重叠。但早期体系没有保证路径上的每台设备会对重复字节选出同一个赢家。

这项不确定性不能被用来夸大成“所有主机都脆弱”,也不能被过滤器用来假设“终点肯定与我一样解释”。只检查、不规范化、也不重组的中间设备,实际上把最终字节选择权交给了另一套实现。

RFC 3128 给出的修复十分窄,却抓住了策略不变量:如果协议是 TCP、偏移量为零,而传输部分短于完整最小首部,就丢弃;偏移量为一的 TCP 分片也继续丢弃。过滤器若要依据端口与标志授权,就必须先确认首片完整暴露了这些最小字段。

这条规则堵住了示例中的八字节替换片,却没有承诺消灭一切 IPv4 歧义。它没有要求每个防火墙做完整重组,也没有规定所有旧主机怎样处理重叠,更没有证明一组获准分片完成了 TCP 握手。网络准入、传输层接受、服务监听与应用效果仍是不同证据层。

后续规范选择了更强边界。RFC 5722 要求 IPv6 一旦发现重叠分片就丢弃整个数据报;RFC 7112 要求 IPv6 第一片包含完整首部链;RFC 6274 回顾 IPv4 的安全问题;RFC 8900 则记录了分片在端点与中间设备行为不一致时的长期脆弱性。

这些后续文件不能倒推某个 2001 年产品必然受影响。它们说明的是同一结构性事实:如果执行策略的设备与最终消费对象的设备并不共享同一份规范化表示,再准确的局部规则也可能失去意义。

这种失配后来反复出现在别处。代理与源站可能用不同方式规范化路径;检测器可能解码一次,而应用再次解码;网关可能在字段合并之前验证对象,下游库却以另一种重复字段规则组合它。它们不是 RFC 3128 的同一攻击,却共享同一种控制缺口:授权依据的字段在授权之后仍可变化。

RFC 3128 的历史价值,最终是一条关于证据的纪律。防火墙日志能证明过滤器看见什么、按哪条规则放行;它不能自动证明终点交给 TCP 的首部是什么,更不能证明连接或入侵成功。只有保留分片集合、重组语义与后续协议状态,才能把准入事实推进到结果事实。

来源