2026 年 9 月 18 日,一名安全研究员公开了四个 Linux 内核本地提权漏洞的完整技术文稿和利用代码:DirtyAH6、TUNderflow、PPPoEject、DiagSpill。这些漏洞藏在内核网络代码里 10 到 21 年,普通本地用户借它们可以拿到 root。本文按运维处置顺序整理一套清单:判断影响、检查攻击面、先做缓解、升级重启,最后用验收收口。

一、四个漏洞分别在哪里
四个漏洞分布在不同的网络子系统,机制各异,但终点相近:内核内存越界写,进而提权。
- DirtyAH6(CVE-2026-80844):IPv6 IPsec(AH6 与 XFRM)在处理路由头时,没有校验 segments_left 与地址数量的关系。构造 hdrlen=2、segments_left=255 的 raw IPv6 包,会让地址指针回退 4064 字节并触发越界 memmove。目标若作为 IPv6 路由器或网关、在 transport 模式下处理 AH,还可能被远程触发崩溃。
- TUNderflow(CVE-2026-81000,CVSS 3.1 7.8):TUN/TAP 保存的接收 headroom 没有上限,Open vSwitch 能把超大的 headroom 传播给它,导致 SKB_MAX_HEAD 下溢,skb 数据区被放到分配范围之外。
- PPPoEject(CVE-2026-68121,CVSS 3.1 7.8):pppoe_sendmsg() 在调用 dev_hard_header() 前保存了指向 skb 头部的指针,而设备回调可能重分配并释放这块内存,后续写入落在已失效的指针上。
- DiagSpill(CVE-2026-74469,CVSS 3.1 8.8):SCTP 的传输计数是 16 位,第 65536 个对端会让计数绕回 0;sctp_diag 预留 0 字节却拷贝完整地址表,约 8 MiB 数据越界写入 Netlink 响应缓冲区。
修复已按稳定分支回移。研究者给出的“四个修复集齐”的首个上游稳定版本为:5.10.270、5.15.221、6.1.188、6.6.157、6.12.109、6.18.50、7.2.4;一批更早的系列(5.11–5.14、5.16–6.0、6.2–6.5、6.7–6.11、6.13–6.17 等)已结束生命周期,没有上游修复,只能依赖发行版或自行评估。
二、为什么值得优先处理
四个理由。第一,利用代码已经公开,而且研究者的 PoC 针对具体发行版和内核做了适配,武器化门槛被明显压低。第二,前三个漏洞的常见利用路径依赖非特权用户命名空间(unprivileged user namespaces),而这在主流发行版上是默认开启的;DiagSpill 更彻底,只要系统启用了 SCTP 和 sctp_diag,连用户命名空间都不需要。第三,研究者测试中 AppArmor 与 SELinux 都没有拦住利用链,别把强制访问控制当补丁。第四,5.10、5.15、6.1、6.6、6.12、6.18 这些长期支持分支都在影响范围内,仍在生命周期内的系统数量不少。
两点补充:官方口径里截至披露日没有确认的在野利用,但 PoC 公开意味着“没被利用”随时可能翻篇;另外,这批漏洞来自研究者用 AI 辅助工具分析内核内存状态与对象布局的实验,属于该系列实验的阶段性成果,方法本身也值得关注。

三、第一步:确认内核带没带修复
先看清自己在哪个版本上运行:
uname -r然后对照上游版本。研究者给出的各分支“四个修复集齐”首个版本是:5.10 系 ≥ 5.10.270、5.15 系 ≥ 5.15.221、6.1 系 ≥ 6.1.188、6.6 系 ≥ 6.6.157、6.12 系 ≥ 6.12.109、6.18 系 ≥ 6.18.50、7.2 系 ≥ 7.2.4。
如果你跑的是发行版内核(RHEL、Debian、Ubuntu 等),直接比较版本号会误判——厂商习惯把补丁回移到旧版本号的内核上。更可靠的是查厂商安全公告,或在机器上检索内核变更记录:
# RHEL 系:在内核变更记录里检索四个 CVE 编号
rpm -q --changelog kernel | grep -iE 'CVE-2026-(74469|81000|68121|80844)'
# Debian/Ubuntu 系:查看当前运行内核包的更新日志
apt-get changelog "linux-image-$(uname -r)" 2>/dev/null | grep -i 'CVE-2026'有输出说明补丁已进入该内核;没有输出也不等于安全,可能只是变更记录未列出——以厂商公告为准,拿不准就向厂商支持渠道确认。
四、第二步:判断攻击面是否可达
可达性取决于几个开关。先看用户命名空间:
# Debian/Ubuntu 特有的开关(1 表示允许非特权用户创建)
sysctl kernel.unprivileged_userns_clone
# 通用上限(大于 0 表示允许创建)
sysctl user.max_user_namespaces再看相关子系统是否存在:
# SCTP 与 sctp_diag(DiagSpill 的前提)
lsmod | grep -E '^sctp'
# TUN/TAP 与 PPPoE
lsmod | grep -E 'tun|pppoe'注意两个容易踩的空子:模块若编译进内核或未加载,lsmod 不一定看得到,需要结合发行版内核配置判断;如果跑容器,要判断的是宿主机内核,宿主机上任何一个满足条件的普通用户或带 CAP_NET_ADMIN 能力的容器进程,都可能碰到这些路径。
五、第三步:不能立即升级时先缓解
缓解思路是把攻击路径先剪掉,但先说清楚:缓解不能替代升级。
其一是关闭非特权用户命名空间,它挡住前三个漏洞的普通用户路径:
# Debian/Ubuntu 系
sysctl -w kernel.unprivileged_userns_clone=0
# 通用写法(较新内核同时支持)
sysctl -w user.max_user_namespaces=0
# 持久化,重启后仍生效
printf 'user.max_user_namespaces = 0\n' > /etc/sysctl.d/99-disable-userns.conf
sysctl --system代价要提前评估:rootless 容器、部分浏览器沙箱(如 bubblewrap)、一些 CI 工具链依赖它;且这招对 DiagSpill 无效。
其二是按需禁用 SCTP,直接堵住 DiagSpill:
printf 'install sctp /bin/false\n' > /etc/modprobe.d/disable-sctp.conf
modprobe -r sctp 2>/dev/null || true # 仍被使用时会失败,属正常TUN 和 PPPoE 也可以按同样思路处理,但这两个在容器、VPN、拨号环境里很常见,动手前先确认没有依赖。把不用的子系统关掉是常规的收敛暴露面手段,但不要把它当成唯一修复。
六、第四步:升级与重启后验收
升级动作本身不复杂,关键是升级完必须重启,并用运行中的内核复核。两类常见发行版的大致路径:
# Debian/Ubuntu 系
apt update && apt full-upgrade
# RHEL 系
dnf update kernel
# 升级后重启,让新内核生效
reboot重启后再跑一次 uname -r,确认不是还在旧内核上:引导默认项没切、独立分区 /boot 空间不足、云厂商控制台自带的救援内核,都可能让机器“升了但没换”。自己编译内核的,还要核对修复提交是否在树上。
容器宿主要额外做一步:重启后容器内看到的 uname -r 应与宿主机一致,再用真实流量路径做一遍业务回归。
七、常见问题排查表
| 现象 | 可能原因 | 处理方向 |
|---|---|---|
| 重启后 uname -r 没变 | 引导默认项仍指向旧内核 | 检查引导配置与新内核安装结果,重新选择启动项 |
| 厂商公告检索不到这四个 CVE | 公告尚未发布或产品线不在范围 | 以厂商支持渠道的答复为准,不凭版本号下结论 |
| 关闭 userns 后容器起不来 | rootless 容器或沙箱依赖用户命名空间 | 评估依赖后恢复,或改为受控的特权方案 |
| modprobe -r sctp 失败 | 仍有进程使用 SCTP | 先停止依赖方;确认业务不用再禁用 |
| 升级后旧硬件驱动异常 | 新内核与老驱动组合的兼容差异 | 查 dmesg,并准备回退旧内核的预案 |
八、验收清单
- uname -r 已是含修复版本,或厂商公告确认补丁已回移。
- 用户命名空间、SCTP、TUN、PPPoE 四个暴露面逐项确认:该关的关、该留的留、理由有记录。
- 暂时无法升级的机器,缓解项已生效并登记例外。
- 重启后业务回归通过,dmesg 无新增异常。
- 变更记录、回退预案和责任人都已归档。
最后提醒两点:这类内核提权漏洞的“已修复”判断,发行版公告比版本号可靠,升级后一定用运行中的版本复核;更不要把公开的利用代码放到生产环境里“试一试”,研究者的 PoC 是针对特定目标适配的,跑错环境可能直接搞崩机器。本文只做处置梳理,没有在任何环境执行利用代码;命令以语法核对与公开官方记录为准。
🔕 评论已关闭