编程 CVE-2026-31431 Copy Fail 深度解析:一次改4字节,拿下root权限——Linux内核加密子系统的致命缺陷

2026-08-08 21:16:30 +0800 CST views 14

CVE-2026-31431 "Copy Fail" 深度解析:一次改4字节,拿下root权限——Linux内核加密子系统的致命缺陷

前言:一个700字节的脚本,如何撬动整台服务器

2026年4月,韩国安全研究团队 Theori 披露了一个编号为 CVE-2026-31431 的 Linux 内核漏洞,代号 "Copy Fail"。这个漏洞的可怕之处不在于它需要多复杂的技术,而在于它的极简攻击面——一个不到 700 字节的 Python 脚本,在单线程、无竞争条件下,就能把一个普通用户提升为 root。整个过程稳定、可复现,且几乎不依赖内核符号信息。

CVSS 3.1 评分 7.8(高危),影响范围覆盖 2017 年至 2026 年修复前几乎所有主流 Linux 发行版——Ubuntu、RHEL、Debian、Fedora、Amazon Linux、欧拉、UOS、麒麟,无一幸免。

本文将从漏洞背景、核心原理、代码级分析、实战复现、检测方法、修复与临时规避六个维度,对这个漏洞进行彻底的深度拆解。目标是让每个看到这篇文章的开发者不仅"知道"这个漏洞,而是真正理解它为什么发生、如何发生、怎么防御

⚠️ 免责声明:本文所有代码仅用于安全研究、漏洞验证和防御加固学习。请勿在未授权环境中测试或利用漏洞。


一、背景:Linux Kernel Crypto API 与 AF_ALG

要理解这个漏洞,首先需要理解 Linux 内核暴露给用户态的加密能力。

1.1 Kernel Crypto API

Linux 内核从很早版本开始就内置了一套完整的加密框架——Kernel Crypto API。这个框架为内核自身以及用户态程序提供了丰富的加密算法实现,包括对称加密(AES、DES)、哈希算法(SHA1、SHA256)、非对称加密(RSA)以及 AEAD(Authenticated Encryption with Associated Data)等。

这套 API 的设计初衷是让内核各子系统(文件系统、网络堆栈等)能方便地使用加密能力,同时也向用户态暴露接口。AEAD 是现代密码学中非常重要的一类算法,它同时提供加密完整性校验,典型代表如 ChaCha20-Poly1305、AES-GCM 等。

1.2 AF_ALG:用户态加密 Socket

Linux 通过一个特殊的 socket 族——AF_ALG(Address Family ALGorithm,family=38)——向用户态程序暴露加密能力。使用方式类似于 TCP/UDP socket:

import socket

# 创建一个 AF_ALG socket
# AF_ALG 是 Linux 特有的,不是 POSIX 标准
alg_fd = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)

# 绑定到指定的算法
# 这里以 authencesn 为例——这是漏洞涉及的核心算法
alg_fd.bind(("aead", "authencesn(hmac(sha1),cbc(aes))"))

# 之后可以通过 sendmsg/recvmsg 与内核加密模块交互

这个接口的设计本身没有问题,它让用户态程序可以在不依赖 OpenSSL 等外部库的情况下调用内核内置的高效加密实现。但问题出在 algif_aead 模块的具体实现中——特别是当它与 splice() 系统调用结合时。

1.3 algif_aead 与 in-place 优化

algif_aead 是 AF_ALG 中处理 AEAD(带关联数据的认证加密)算法的内核模块。内核开发者在 2017 年左右为它引入了一个性能优化in-place 操作(原地操作)。

传统的加密操作通常是:

输入缓冲区 [input]  →  加密处理  →  输出缓冲区 [output]

In-place 优化后:

输入/输出缓冲区复用同一块内存 [buf]  →  加密处理(就地完成)

这减少了内存分配和数据拷贝,对性能有明显提升。但这个优化引入了一个微妙的假设:当源缓冲区和目标缓冲区是同一块内存时,内核可以安全地将这块内存视为可写的。

问题来了——当攻击者精心构造数据路径,让来自文件 page cache 的页面(本应是只读的源数据)被当作可写的目标缓冲区使用时,这个假设就被打破了。

1.4 splice():零拷贝的隐患

splice() 是 Linux 提供的一个系统调用,可以在两个文件描述符之间零拷贝传输数据。它的典型用法包括:

  • 将文件内容直接送入管道:splice(fd, NULL, pipe_fd, NULL, size, SPLICE_F_MOVE)
  • 将管道数据直接写入文件:splice(pipe_fd, NULL, fd, NULL, size, SPLICE_F_MOVE)
  • 在 socket 和文件之间传输数据

零拷贝的好处是避免了在用户态和内核态之间反复拷贝数据。但 splice 的副作用是数据页的所有权和语义变得复杂——页面可能在不同上下文之间流转,内核需要小心维护"谁可以写、谁只能读"的状态。

CVE-2026-31431 的核心漏洞就出现在 algif_aead 处理 splice() 数据路径时,没有正确区分"应该被当作源(只读)"和"可以被当作目标(可写)"的缓冲区。


二、漏洞原理:从"本应失败"到"可控写入"

2.1 攻击的核心思路

漏洞利用的整体思路可以用三句话概括:

  1. 通过 splice() 将一个可读文件的 page cache 页面注入到 AEAD 解密操作的输入路径中
  2. 利用 algif_aead 的 in-place 解密优化,让这个页面同时成为"解密输出目标"
  3. AEAD 认证解密失败(tag 不匹配),但已经写入了 4 字节的密文解密结果到 page cache 中

关键点在于第三步:AEAD 认证加密模式(尤其是 authencesn)有一个特性——它在处理数据时会先将密文写入输出缓冲区,然后才验证认证标签。如果标签验证失败,操作会返回错误,但已经写入的那部分数据不会回滚。

在正常场景下,这是无害的——输出缓冲区本来就是用户态分配的可写内存。但在攻击者精心构造的数据路径下,当 page cache 页面通过 splice 进入这个流程时,内核错误地将其放入了"输出 scatterlist"(目标缓冲区列表),导致解密出的 4 字节被写入了 page cache。

2.2 根因分析:scatterlist 混淆

在 Linux 内核的加密实现中,数据以 scatterlist(分散-聚集列表)的形式组织。一个 scatterlist 描述了一系列内存区域,告知加密引擎"从哪里读输入数据,写入到哪里"。

正常的数据路径:

用户态 buffer(可写)→ 设置为"读源"
                    → 设置为"写目标"
                    → 加密操作完成(输入=输出,同一块内存,in-place)

攻击者构造的数据路径:

文件 page cache(只读)→ 通过 splice 注入到 scatterlist
                      → 被设置为"读源"
                      → 但因为 in-place 优化的实现缺陷,也被设置为"写目标"
                      → 解密结果写入 page cache → 成功污染

内核的 crypto_aead_decrypt() 或类似函数在处理 authencesn 的 in-place 路径时,会遍历 scatterlist。问题出在 aead_copy_frags 或类似的辅助函数中——它没有正确检查"这块内存是否真的来自 page cache 且不应该被写入"。

2.3 精确控制:为什么是4字节?

答案藏在内核代码中 authencesn 的实现细节里。AEAD 算法在解密时,会先将数据拷贝到一个临时缓冲区(通常是 4 字节对齐的),处理完成后再写回。如果在这个过程中出现错误(例如认证标签不匹配),写回操作可能只完成了一部分——恰好是 4 字节。

这就是为什么公开的 exploit 每次写入固定 4 字节。攻击者无法一次性写入任意长度,但可以通过多次调用逐步修改 setuid 二进制文件的任意位置:

# 伪代码:多次写入以覆盖 ELF 入口点
for offset in range(0, len(shellcode), 4):
    write_4_bytes_at_offset(target_file, offset, shellcode_chunk)

2.4 为什么不会触发文件哈希检测?

这是这个漏洞最"狡猾"的地方。攻击者修改的是 page cache——操作系统为磁盘文件在内存中维护的缓存。修改 page cache 不等于修改磁盘文件:

用户修改文件 → 操作系统先写入 page cache
            → 操作系统决定何时将修改同步回磁盘(dirty page writeback)
            → 如果文件没有再次被访问或系统没有 sync,磁盘上的原始内容保持不变

即使攻击者修改了 /usr/bin/su 的 page cache,在 page cache 被回收(系统重启、内存压力触发、文件被覆盖)之前:

  • ls -la /usr/bin/su 显示文件时间戳不变
  • sha256sum /usr/bin/su 显示哈希不变(因为读的是磁盘)
  • 只有当程序被执行时,才会从 page cache 加载被污染的代码

这也意味着磁盘文件哈希检测无法发现这个漏洞的利用


三、漏洞利用分析:跨架构的通用 exploit

3.1 exploit 架构

研究团队发布的 exploit 仓库(theori-io/copy-fail-CVE-2026-31431)支持多个 CPU 架构:

架构Payload 大小特点
x86-64160 字节通用,覆盖大多数服务器
i386126 字节32 位系统
AArch64 (ARM64)172 字节苹果 M 系列、ARM 服务器
ARMv7138 字节32 位 ARM 设备

所有架构的 payload 都可以在同一套逻辑下工作——这得益于漏洞利用的是内核加密子系统的通用实现,而不是特定于某架构的代码。

3.2 核心利用步骤

#!/usr/bin/env python3
"""
CVE-2026-31431 Copy Fail - 简化版利用流程(注释版)
实际 exploit 代码请参考官方仓库: https://github.com/theori-io/copy-fail-CVE-2026-31431
"""

import os
import socket
import struct
import ctypes

AF_ALG = 38
SOL_ALG = 279

# ==================== 第一步:建立 AF_ALG socket ====================
# 创建一个 AF_ALG socket,用于与内核加密子系统通信
sock = socket.socket(AF_ALG, socket.SOCK_SEQPACKET, 0)

# ==================== 第二步:绑定 authencesn 算法 ====================
# authencesn 是 AEAD 算法的一种,漏洞就出现在这个算法的 in-place 处理路径中
# authencesn(hmac(sha1),cbc(aes)) 表示:认证使用 HMAC-SHA1,加密使用 CBC-AES
sock.bind(("aead", "authencesn(hmac(sha1),cbc(aes))"))

# ==================== 第三步:获取文件 page cache 的文件描述符 ====================
# 打开目标 setuid 程序,这里以 /usr/bin/su 为例
target_path = "/usr/bin/su"
target_fd = os.open(target_path, os.O_RDONLY)

# ==================== 第四步:通过 splice 将 page cache 注入到加密流程 ====================
# 关键步骤:通过 splice() 系统调用,将目标文件的 page cache 页面
# 注入到 AF_ALG socket 的发送路径中
#
# 内核在处理 splice → AF_ALG 的组合路径时,会将 page cache 页面
# 错误地放入解密操作的"输出目标"位置
#
# 这里需要创建一个管道作为中介:
pipe_rd, pipe_wr = os.pipe()

# 从目标文件 splice 到管道(此时 page cache 被加载到内存)
os.splice(target_fd, pipe_rd, pipe_wr, ...)  # 实际调用更复杂

# 从管道 splice 到 AF_ALG socket
# 内核在这里将 page cache 页面错误地设置为"可写目标"
os.splice(pipe_rd, ..., sock, ...)  # 实际调用更复杂

# ==================== 第五步:构造解密请求 ====================
# 发送精心构造的解密请求
# 关键:认证标签(tag)是精心设计的,使得:
# 1. 认证验证会"部分"通过
# 2. 解密操作执行了一部分
# 3. 恰好有 4 字节被写入 page cache
# 4. 最终返回认证错误
sock.send(crafted_decrypt_request)

# ==================== 第六步:触发 setuid 程序执行 ====================
# 此时被污染的 page cache 已被加载到内存
# 当 /usr/bin/su 被执行时,CPU 从被污染的 page cache 中取指
# 攻击者的 shellcode 被执行 → 获得 root shell
os.system("/usr/bin/su")

3.3 提权的核心:ELF 入口点覆盖

公开的通用 exploit 采用的是 ELF 入口点覆盖策略:

  1. 选择目标:ELF 可执行文件的入口点(_start 或 main 的 prologue)
  2. 构造 shellcode:一小段能在 setuid root 上下文中打开 /bin/sh 的机器码
  3. 多次写入:每次写入 4 字节,覆盖入口点的不同部分
  4. 执行触发:运行被污染的 setuid 程序,跳转到被覆盖的入口点 → shellcode 执行 → root shell

为什么选择入口点?因为入口点通常包含固定的、已知长度的 prologue 代码,攻击者可以精确计算出需要覆盖哪些字节:

# x86-64 典型入口点 prologue(被覆盖前)
_start:
    xor ebp, ebp              ; 3 字节
    mov rsi, rsp              ; 2 字节
    and rsp, 0xfffffffffffffff0  ; 4 字节
    mov rdi, qword ptr [rsp]  ; 3 字节
    call __libc_start_main    ; 5 字节
    
# 攻击者只需要覆盖前面的几个字节,替换为跳转到 shellcode 的指令

四、环境检测:判断系统是否暴露于攻击面

4.1 快速暴露面检测脚本

下面的脚本不会执行提权,也不会修改任何系统文件。它只检测当前用户是否可以访问 AF_ALG AEAD 接口——这是漏洞利用的必要前提条件。

#!/usr/bin/env python3
"""
CVE-2026-31431 暴露面检测脚本(非破坏性)
用法: python3 check_exposure.py
退出码: 0=未暴露, 2=已暴露(可能存在漏洞)
"""

import os
import sys
import platform
import subprocess

AF_ALG = getattr(socket, "AF_ALG", 38) if 'socket' in dir() else 38

try:
    import socket
    AF_ALG = socket.AF_ALG
except AttributeError:
    # AF_ALG 在某些平台上不可用
    print("[-] AF_ALG socket family not available on this platform")
    sys.exit(0)

# 测试的 AEAD 算法(按优先级排列)
AEAD_CANDIDATES = [
    "authencesn(hmac(sha1),cbc(aes))",
    "authenc(hmac(sha1),cbc(aes))",
    "authencesn(hmac(sha256),cbc(aes))",
]


def run_cmd(cmd):
    """执行命令并返回输出"""
    try:
        return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.DEVNULL).strip()
    except Exception:
        return ""


def check_algif_aead_loaded():
    """检查 algif_aead 内核模块是否加载"""
    result = run_cmd("lsmod | grep algif_aead")
    return bool(result)


def check_proc_crypto():
    """检查 /proc/crypto 中是否有 authencesn 相关算法"""
    try:
        with open("/proc/crypto", "r") as f:
            content = f.read()
            return "authencesn" in content or "authenc" in content
    except Exception:
        return False


def check_kernel_config():
    """检查内核是否配置了 AF_ALG AEAD 支持"""
    # 尝试多个可能的配置文件位置
    uname_r = platform.release()
    configs = [
        "/proc/config.gz",
        f"/boot/config-{uname_r}",
        f"/lib/modules/{uname_r}/build/.config",
    ]
    
    for cfg in configs:
        result = run_cmd(f"zcat {cfg} 2>/dev/null | grep CONFIG_CRYPTO_USER_API_AEAD || "
                        f"cat {cfg} 2>/dev/null | grep CONFIG_CRYPTO_USER_API_AEAD || true")
        if "CONFIG_CRYPTO_USER_API_AEAD=y" in result or "CONFIG_CRYPTO_USER_API_AEAD=m" in result:
            return result.strip()
    return "not found"


def try_afalg_aead(alg_name):
    """尝试绑定 AF_ALG AEAD 算法"""
    try:
        s = socket.socket(AF_ALG, socket.SOCK_SEQPACKET, 0)
        s.bind(("aead", alg_name))
        s.close()
        return True, None
    except OSError as e:
        return False, f"errno={e.errno} {e.strerror}"
    except Exception as e:
        return False, str(e)


def main():
    import socket
    
    print("=" * 60)
    print("CVE-2026-31431 Copy Fail - 暴露面检测")
    print("=" * 60)
    print()
    
    print(f"[*] 内核版本: {platform.release()}")
    print(f"[*] 用户: uid={os.getuid()} euid={os.geteuid()}")
    print(f"[*] 平台: {platform.system()} {platform.machine()}")
    print()
    
    # 检查内核配置
    config = check_kernel_config()
    print(f"[*] CONFIG_CRYPTO_USER_API_AEAD: {config}")
    
    # 检查模块是否加载
    loaded = check_algif_aead_loaded()
    print(f"[*] algif_aead 模块: {'已加载' if loaded else '未加载'}")
    
    # 检查 /proc/crypto
    has_crypto = check_proc_crypto()
    print(f"[*] /proc/crypto 包含 AEAD 算法: {'是' if has_crypto else '否'}")
    
    print()
    print("[*] 尝试访问 AF_ALG AEAD 接口...")
    print("-" * 60)
    
    exposed = False
    for alg in AEAD_CANDIDATES:
        ok, err = try_afalg_aead(alg)
        if ok:
            print(f"[+] 可访问: {alg}")
            exposed = True
        else:
            print(f"[-] 不可访问: {alg} ({err})")
    
    print()
    print("=" * 60)
    if exposed:
        print("[!] 结果: 当前用户可以访问 AF_ALG AEAD 接口")
        print("[!] 如果内核未修复,此系统存在被提权的风险")
        print("[!] 建议: 立即检查内核安全公告并应用修复补丁")
        sys.exit(2)
    else:
        print("[+] 结果: AF_ALG AEAD 接口不可访问")
        print("[+] 可能原因: 模块未加载 / 策略限制 / 架构不支持")
        print("[+] 此系统在当前用户上下文下不存在直接暴露面")
        sys.exit(0)


if __name__ == "__main__":
    main()

4.2 快速诊断命令清单

在任意 Linux 终端中执行以下命令,快速判断系统状态:

# 1. 查看内核版本
uname -r

# 2. 检查 algif_aead 模块是否加载
lsmod | grep algif_aead

# 3. 查看内核加密接口
cat /proc/crypto | grep -E 'authencesn|aead|name' | head -20

# 4. 检查内核配置
cat /proc/config.gz 2>/dev/null | zcat | grep CONFIG_CRYPTO_USER_API_AEAD
# 或
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r) 2>/dev/null

# 5. Ubuntu/Debian 安全更新检查
apt list --upgradable 2>/dev/null | grep -E 'linux-image|linux-generic|linux-base'

# 6. RHEL/Fedora 安全更新检查
dnf updateinfo list --cves 2>/dev/null | grep CVE-2026-31431

# 7. 查看已安装的内核版本(多版本共存时)
dpkg -l | grep linux-image  # Debian/Ubuntu
# 或
rpm -qa | grep kernel  # RHEL/Fedora

五、修复方案:多层次的防御策略

5.1 首选方案:升级内核

最根本的修复方式是升级到发行版官方发布的包含 CVE-2026-31431 修复补丁的内核版本

Ubuntu / Debian:

# 更新软件包列表
sudo apt update

# 查看可用的内核更新
apt list --upgradable | grep -E 'linux-image|linux-generic|linux-base'

# 执行完整升级(会同时升级所有软件包)
sudo apt full-upgrade -y

# 如果只想升级内核
sudo apt install --only-upgrade linux-image-$(uname -r) -y

RHEL / Rocky / AlmaLinux / Fedora:

sudo dnf check-update
sudo dnf update kernel -y
# 或升级所有软件包
sudo dnf update -y

SUSE:

sudo zypper patch
# 或指定 CVE
sudo zypper patch --cve=CVE-2026-31431

升级后必须重启才能加载新内核:

sudo reboot

重启后验证:

# 确认运行的是新内核
uname -r

# 确认没有已知的高危漏洞
cat /proc/version

5.2 临时规避:禁用 algif_aead 模块

如果无法立即重启或升级内核(生产环境常见),可以先禁用 algif_aead 模块来阻止攻击面:

# 创建模块黑名单配置
echo "install algif_aead /bin/true" | sudo tee /etc/modprobe.d/disable-algif-aead.conf

# 立即卸载已加载的模块(如果可以的话)
sudo rmmod algif_aead 2>/dev/null || echo "模块未加载或无法卸载(正常,如果模块没有显式加载)"

# 验证:检查模块是否在黑名单中
cat /etc/modprobe.d/disable-algif-aead.conf

# 再次检查 lsmod 是否还有 algif_aead
lsmod | grep algif_aead || echo "algif_aead 不在已加载模块列表中"

注意:即使模块不在 lsmod 输出中,如果内核编译时将 CONFIG_CRYPTO_USER_API_AEAD 编译为内置(y 而不是 m),用户仍可能通过 modprobe 动态加载它。/etc/modprobe.d/disable-algif-aead.conf 中的 install 指令可以确保即使有人尝试加载模块,也会被替换为 true(空操作)。

5.3 容器/沙箱环境的特殊处理

Kubernetes / Docker 节点:

如果你的容器运行在共享内核的主机上(这是 Docker 的默认模式),容器内的漏洞利用同样可以影响宿主机——因为内核漏洞的利用不依赖 namespace 隔离。

容器内普通用户 
    ↓ (通过 /proc 或 socket)
宿主机内核 ← CVE-2026-31431 在这里被利用
    ↓
容器逃逸 + root 提权

缓解措施:

  1. 确保宿主机内核已升级到修复版本
  2. 考虑使用 gVisorKata Containers 等内核隔离方案(但这些方案本身也有攻击面)
  3. 在 Kubernetes 中使用 Security Context 限制容器 capabilities:
securityContext:
  # 移除 CAP_SYS_ADMIN 可以阻止 splice() 在某些路径上的使用
  capabilities:
    drop:
      - CAP_SYS_ADMIN
  1. 启用 seccomp 过滤,阻止 socket(AF_ALG, ...) 调用:
{
  "names": ["socket"],
  "action": "SCMP_ACT_ERRNO"
}

但注意:这可能影响需要使用 AF_ALG 的合法应用。

在线代码执行平台 / Notebook 环境:

这类平台是 CVE-2026-31431 的高危场景,因为它们需要执行用户提交的不可信代码:

  • Jupyter Notebook 服务器
  • 在线评测系统(OJ)
  • 代码实验平台
  • 沙箱执行环境

紧急措施:

  1. 在内核层面应用修复或禁用模块
  2. 如果使用容器隔离,确保容器不以 privileged 模式运行
  3. 考虑将内核升级为多版本共存,允许在线切换

六、为什么这个漏洞值得警惕:深度反思

6.1 漏洞的"优雅"之处

CVE-2026-31431 之所以在安全社区引起广泛关注,不仅仅因为它的高危评分,更因为它的利用美学

极简攻击面:不需要复杂的竞争条件,不需要 ROP/JOP 链,不需要喷堆(heap spray),甚至不需要知道目标系统的内核符号表。一个 Python socket 调用 + splice + 精心构造的数据,就能完成提权。

跨架构通用性:同一个漏洞原理,在 x86-64、i386、ARM64、ARMv7 上都能工作。payload 代码量不到 200 字节。

隐蔽性:不修改磁盘文件,page cache 被污染后文件哈希不变,系统日志可能完全不记录任何异常。

确定性:单线程、零竞争,在大多数环境下可以稳定复现。

6.2 对内核安全的警示

这个漏洞暴露了 Linux 内核加密子系统在处理复杂数据路径组合时的脆弱性:

  1. In-place 优化的危险性:性能优化往往引入微妙的状态假设。当这些假设在非预期的数据路径下被触发时,就会产生安全漏洞。

  2. 系统调用组合的不可预测性:单独看 splice() 是安全的,单独看 AF_ALG 也是安全的,但它们组合在一起时产生了漏洞。这提醒我们:系统调用之间的交互是内核安全研究的重要方向

  3. page cache 的双重语义:page cache 在大多数情况下是"只读的数据来源",但在内核的某些代码路径中,它可能被当作"可写的目标缓冲区"。这种语义混淆是漏洞的根本原因。

6.3 给开发者的建议

作为一线开发者,你可能不会直接修改内核代码,但这个漏洞仍然值得你关注:

了解你的运行环境:知道你的服务器跑的是什么内核版本,发行版的安全更新是否及时。

不要依赖"隔离"作为唯一防线:Docker 容器、Kubernetes pod 都不提供内核隔离。在共享内核的模式下,内核漏洞就是你的容器边界漏洞。

建立漏洞响应机制:CVE-2026-31431 的披露提醒我们,高危内核漏洞可能随时出现。你需要一套机制来:快速评估影响范围 → 决定是否需要紧急停机 → 执行修复升级 → 验证修复效果。

CI/CD 环境的安全加固:CI/CD Runner 往往以较高权限运行构建和测试代码。如果 Runner 执行来自 PR 的不可信代码,这个漏洞可能成为攻击者的入口。


七、总结:漏洞全景图

维度内容
CVE 编号CVE-2026-31431
代号Copy Fail
漏洞类型Linux Kernel 本地权限提升
影响组件algif_aead / AF_ALG / Kernel Crypto API
利用前提本地普通用户账号、可访问 AF_ALG AEAD 接口
攻击复杂度低(无需竞争条件、零依赖)
影响结果普通用户 → root
CVSS 3.1 评分7.8(高危)
影响范围2017-2026 年主流 Linux 发行版内核
核心原理splice() + AF_ALG AEAD in-place 优化 → page cache 可控写入
写入粒度每次 4 字节(可多次调用覆盖任意位置)
修复方式升级内核 或 禁用 algif_aead 模块
公开时间2026 年 4 月(Theori 团队披露)

参考资料:

  • 原始漏洞报告:https://copy.fail/
  • NVD 详情:https://nvd.nist.gov/vuln/detail/CVE-2026-31431
  • 欧盟 CERT 公告:https://cert.europa.eu/publications/security-advisories/2026-005/
  • 官方 Exploit 仓库:https://github.com/theori-io/copy-fail-CVE-2026-31431
  • Sysdig 技术分析:https://www.sysdig.com/blog/cve-2026-31431-copy-fail-linux-kernel-flaw-lets-local-users-gain-root-in-seconds

推荐文章

为什么大厂也无法避免写出Bug?
2024-11-19 10:03:23 +0800 CST
php指定版本安装php扩展
2024-11-19 04:10:55 +0800 CST
Vue 3 中的 Watch 实现及最佳实践
2024-11-18 22:18:40 +0800 CST
Rust 与 sqlx:数据库迁移实战指南
2024-11-19 02:38:49 +0800 CST
使用 sync.Pool 优化 Go 程序性能
2024-11-19 05:56:51 +0800 CST
如何实现虚拟滚动
2024-11-18 20:50:47 +0800 CST
介绍 Vue 3 中的新的 `emits` 选项
2024-11-17 04:45:50 +0800 CST
程序员茄子在线接单