bootsareme/copyfail-deconstructed
GitHub: bootsareme/copyfail-deconstructed
该项目是对 CVE-2026-31431 Linux 内核提权漏洞的通俗易懂版解构,通过详细注释的代码解释了利用 crypto API 页缓存损坏实现本地 root 提权的完整攻击链。
Stars: 1 | Forks: 1
# copyfail 解构
[CVE-2026-31431](https://nvd.nist.gov/vuln/detail/CVE-2026-31431) 的通俗易懂版本,这是一种允许任何用户获取 root 权限的提权技术。最初的漏洞概念验证代码可以在这里找到:https://github.com/theori-io/copy-fail-CVE-2026-31431,但经过了高度压缩和精简,以使其占用空间尽可能小。本仓库试图以更具可读性的方式来解析该代码,包括代码的功能、payload 的加载方式,以及如何针对不同的架构进行攻击。更多技术分析请参见:https://xint.io/blog/copy-fail-linux-distributions。
## 用法
默认情况下,运行 `python3 copyfail.py` 将执行针对 `/usr/bin/su` 漏洞利用的 x64 shellcode。你可以通过运行 `python3 copyfail.py [path/to/custom/payload.elf]` 来提供自己的 payload。作为示例,`payloads/` 目录中包含了一个 ARM64 的 shellcode 汇编代码。因此,要在 ARM64 设备上进行测试,你首先需要使用我们自定义的链接器脚本构建一个精简的 payload:
```
as -o shellcode_aarch64.o payloads/shellcode_aarch64.S
ld -nostdlib -static -o shellcode_aarch64.elf shellcode_aarch64.o
strip -s shellcode_aarch64.elf
```
然后你可以使用 `python3 copyfail.py shellcode_aarch64.elf` 来运行主漏洞利用程序。
对于 C 语言版本的运行:
1. 构建(见下文)
2. `./c_copyfail` 运行与上述相同的默认 shellcode。
- 同样,你可以通过运行 `./c_copyfail [path/to/custom/payload.elf]` 来提供自己的 payload。
构建 C 语言版本:
```
cd c_port
make
```
具体来说,这会将目标 .S 文件编译为原始二进制文件,并将其输出为 C 语言的无符号字符数组:
```
gcc -c payloads/[shellcode].S
objcpy -O binary [shellcode].o [payload].raw
xxd -i [payload].raw > payload.txt
```
然后你可以将此文件的内容复制到你的源代码中。
## 修复
为防止被利用,请运行:
```
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
```
如果已被利用,你可以重启机器,或者运行:
`echo 3 | sudo tee /proc/sys/vm/drop_caches`
## 原理说明
1. 内核允许用户通过 socket 类型 `AF_ALG` 与 crypto API 进行通信
- 2017 年,"就地优化 (in-place optimisation)" 被添加到 crypto API 的 algif_aead 部分
- 当数据通过 splice() 系统调用通过 socket 发送时,内核会将你拼接的文件的实际页缓存页 (page-cache pages) 放入 crypto 工作区
- Crypto 算法 authencsn 会将其输出缓冲区视为临时空间,并在其预期位置之后写入 4 个字节
2. 理论上攻击者可以做什么
- 选择任何可读文件(例如本例中的 /usr/bin/su)
- 在该文件中选择要发生 4 字节写入的偏移量
- 选择要写入的 4 字节值(AEAD 操作中关联数据的一部分)
- 编写 shellcode 覆盖内存中的文件
3. 通过覆盖页缓存获取 root 权限
- 内核永远不会将损坏的页标记为 dirty,文件看起来没有被更改
- 当执行 /usr/bin/su 时,内核会从页缓存中读取它并获取被修改的字节
- 通过重复 4 字节写入(大约 40 次),它们可以覆盖 /usr/bin/su 内部的 UID 检查,从而使 UID 变为 0 (root)
- 任何用户都能成功获取 root shell
4. 修复措施
- 刷新页缓存以移除内存中被修改的文件,这样下次就会从磁盘读取
- 卸载内核模块
- 将其加入加载黑名单
- 如果是内置模块,你必须使用 seccomp 或 eBPF 阻止系统调用。或者将其从初始化过程中移除并重新启动机器。
'su' 二进制文件已在内存中被损坏,因此文件修改不会被检测到。要从磁盘恢复,你可以刷新页缓存。
标签:ARM64, CVE-2026-31431, EXP, Linux提权, PoC, Python, Root提权, Shellcode, Web报告查看器, x64, 内核漏洞, 协议分析, 客户端加密, 技术调研, 无后门, 暴力破解, 本地提权, 权限提升, 汇编, 漏洞分析, 漏洞复现, 网络安全, 路径探测, 逆向工具, 隐私保护