Ip-fragment攻击是什么?
互联网安全 2026-09-18 15:20 651

IP 分片攻击是一类利用 IPv4(及 IPv6)分片与重组机制的攻击统称。它的危害呈现三种完全不同的形态:用畸形分片把目标打崩、用重叠分片绕过检测、用分片洪泛耗尽目标资源。三者共用同一套底层机制,但攻击目标和防御手段各不相同。

先补基础:分片为什么存在

链路层有 MTU 限制(以太网通常是 1500 字节),当 IP 数据报大于路径 MTU 时就必须分片。IPv4 首部里有三个字段为此服务:标识符(16 位,同属一个数据报的分片共用)、标志位(DF 表示禁止分片,MF 表示后面还有分片)、分片偏移(13 位,以 8 字节为单位)。

这几个字段藏着两个关键约束,也是大量攻击的根源。

其一,偏移以 8 字节为单位,所以除最后一片外,每个分片的载荷长度必须是 8 的倍数,首片若小于 20 字节就无法容纳完整的 TCP 首部——这正是 Tiny Fragment 攻击的前提。

其二,13 位偏移乘以 8 字节加最大载荷即 65535,与首部总长度字段同级,这个上限的算术处理稍有闪失就是缓冲区溢出——Ping of Death 与 Teardrop 都源于此。

另一个关键点是:IPv4 允许中间路由器分片,重组只在最终目的地进行。这意味着目标必须维护重组队列、分配缓冲区、设置超时(典型 30 到 60 秒)。分片机制天然带来状态和资源开销,这就是攻击面所在。

三类攻击

类型 代表手法 攻击目标
畸形与重叠分片 Teardrop、Ping of Death、Jolt2、FragmentSmack 触发重组越界或 CPU 耗尽,造成崩溃或严重性能下降
重叠分片绕过 Tiny Fragment、重叠策略差异利用 让检测设备与目标主机看到不同内容,绕过 IDS 与访问控制
分片洪泛 只发首片不发后续、高频小分片 占满重组队列与缓冲区,等待超时释放
隐蔽通道 数据藏于分片、分片头滥用 绕过深度包检测、外泄数据

第一类:畸形分片把目标打崩

Teardrop(1997)是最经典的案例。攻击者构造偏移相互重叠的分片,使重组时计算出负数长度或越界写入,导致 BSD、Linux、Windows 等系统崩溃。同期还有一批变种(NewTear、Bonk、Rose),原理相同。

Ping of Death(1996)看似是 ICMP 攻击,本质却是分片攻击:构造分片序列使重组后的总长度超过 65535,把固定大小的重组缓冲区挤爆。这也是前面校订 ICMP 那段时提到的重点。

Jolt2(2000)思路不同,它把同一个标识符的大量"最后一片"持续发给 Windows 系统,使重组队列的查找算法陷入高复杂度计算,CPU 直接打满。

FragmentSmack(CVE-2018-5391)说明这类问题并非历史。Linux 内核在分片重组时存在哈希冲突导致的算法复杂度问题,攻击者用很小带宽的小分片就能把内核态 CPU 耗尽。Windows 也存在对应的问题。这类漏洞的修复方式是打补丁,没有替代方案。

第二类:重叠分片绕过检测

这是分片攻击中最有价值、也最常被低估的一类。它的核心不是打垮谁,而是制造认知分歧。

所谓分片重叠,是指两个分片的偏移区间有交叠,交叠部分的字节内容不一致。此时"该采用谁的内容"在规范里并未强制统一,各实现自行其是:传统 BSD 系多为"先到优先",Linux 与 Windows 多采用"后到覆盖",还有实现对首片、末片采取不同策略。

这给了攻击者操作空间:只要让 IDS 按一种策略重组、让目标主机按另一种策略重组,就能做到检测设备看到的是无害内容,而主机执行的是恶意载荷。 这就是所谓的"插入与规避"。

Tiny Fragment 是另一种玩法。把 TCP 首部拆进多个极小的分片,第一个分片只含 8 字节,连端口号都读不全。只检查首片的过滤设备据此做出的放行判断,对后续分片毫无意义。RFC 3128 专门讨论了这一变种的防护。

1998 年 Ptacek 与 Newsham 的论文《Insertion, Evasion, and Denial of Service》系统性地形式化了这类手法,奠定了入侵检测领域"目标基重组"的理论基础,至今仍是必读文献。

第三类:分片洪泛耗尽资源

思路与 SYN 洪泛同源:占住资源不释放。

一种是发送大量只有首片、永不成套的分片。目标会为每个未完成的重组队列保留缓冲区并启动计时器,队列被占满后正常流量的分片无法重组,全部丢弃。攻击者只需很小的带宽,就能让目标的可用重组内存归零。

另一种是高频发送大量小分片,持续触发重组路径的分配与释放,消耗 CPU。 FragmentSmack 就是这一类的极端案例。

为什么难防

分片是 IP 层的合法机制,不能一刀切封禁——VPN 隧道、UDP 大响应、DNSSEC 大包都可能依赖分片,封掉会引发难以定位的故障。更根本的困难在于实现差异无法被规范消除:规范只规定必须支持重组,没有规定重叠时该听谁的,只要差异存在,规避空间就存在。此外,重组天然需要状态与内存,这个资源消耗点是无法通过设计消除的。

检测

抓包层面的异常特征很好识别:大量只有首片的分片;偏移区间重叠;载荷长度不是 8 的倍数或极小分片的出现;同一标识符的分片数异常多;分片在重组超时后仍不完整。

Wireshark 常用过滤表达式:ip.flags.mf == 1 抓所有后续分片;ip.frag_offset > 0 抓非首片;ip.frag_offset == 0 && ip.flags.mf == 1 抓首片。重叠需要结合重组提示或脚本统计偏移区间来判断。

主机侧看重组计数器。Linux 下 netstat -s 中的分片相关项,以及 /proc/net/snmp 里的 ReasmReqds、ReasmFails、ReasmTimeout、FragFails,异常增长都是直接信号——尤其是 ReasmFails 与 ReasmTimeout 同时上升,基本可以确定存在不完整分片洪泛。

流量侧则用 NetFlow 统计分片流量占比,与历史基线比对。正常网络里分片比例通常很低,占比突然跳升本身就是告警条件。

防御

补丁是治本手段。 参考实现今天对已知的畸形与重叠场景已有明确处理,真正暴露在风险中的是嵌入式设备、工控设备、老旧网络设备——它们的分片实现常年不更新,是这类攻击的主要受害者。

规范层面已有明确建议。 RFC 5722 要求 IPv6 直接丢弃重叠分片;RFC 1858 建议对 IPv4 采取同样的严格策略。安全设备与终端只要统一采用"丢弃重叠分片",规避空间就被关闭。

边界设备做分片治理。 限制分片速率、设置重组队列上限、丢弃偏移异常与过小分片。丢弃所有非首片是一种粗放但有效的加固手段,代价是可能影响合法的分片流量,只建议用在对外服务单一、可接受该代价的场景。

主机侧重组参数要收紧:

net.ipv4.ipfrag_high_thresh = 4194304
net.ipv4.ipfrag_low_thresh  = 3145728
net.ipv4.ipfrag_time        = 30
net.ipv4.ipfrag_max_dist    = 64

前两项控制重组内存上限,超出后较早的队列被丢弃;第三项缩短超时,减少资源被占用的窗口;第四项限制乱序距离,收窄异常分片的处理范围。

检测侧必须启用目标基重组。 让 IDS 采用与受保护主机一致的重组策略,从根上消除"检测端与终端看法不一致"这一前提。现代 IDS 基本都提供该配置项,但默认值未必与你的主机匹配,需要显式确认。

避免一刀切封禁。 全面拒绝分片会破坏 PMTUD、隧道与部分合法大包流量,引发难查的故障。正确做法是丢弃畸形与重叠、限制速率、放行规范分片。

经典案例时间线

1996 年 Ping of Death 与 1997 年 Teardrop 奠定了这一领域的认知;1998 年 Ptacek 与 Newsham 的论文把分片从"崩溃手段"升级为"规避理论";2000 年 Jolt2 展示了纯 CPU 消耗的可能性;2018 年 FragmentSmack 证明二十年过去,协议栈的实现缺陷依然会以新的形式出现。

Powered by ©智简魔方