rfxn/copyfail

GitHub: rfxn/copyfail

针对 CVE-2026-31431 Linux 内核 AF_ALG 本地提权漏洞的纵深防御工具包,提供用户态 LD_PRELOAD 阻断、内核模块黑名单和安全态势审计,无需重启即可部署。

Stars: 5 | Forks: 0

# copyfail - CVE-2026-31431 **通过 AF_ALG `authencesn` 页缓存原语实现本地提权。** 内核在对 AEAD 解密时发生边界计算错误,将攻击者可控的字节写入任意 SUID 二进制文件或特权配置文件的页缓存中。 磁盘上的文件没有任何更改;这种破坏仅存在于 RAM 中直到被驱逐。 不会留下任何磁盘上的取证痕迹。 用户态纵深防御:一个阻断 `AF_ALG` socket 创建的 `LD_PRELOAD` shim 以及一个只读的主机安全态势审计工具。 已签名的适用于 EL8 / EL9 / EL10 的 RPM 包。 copyfail yum/dnf package repo Deep-dive research article on rfxn.com [![CVE](https://img.shields.io/badge/CVE-2026--31431-d97757?labelColor=09090b)](#what-this-protects-against) [![Severity](https://img.shields.io/badge/severity-LOCAL%20PRIVESC-d44d4d?labelColor=09090b)](#what-this-protects-against) [![License](https://img.shields.io/badge/license-GPL--2.0-22d3ee?labelColor=09090b)](LICENSE) [![EL8/9/10](https://img.shields.io/badge/EL-8%20%2F%209%20%2F%2010-4ade80?labelColor=09090b)](https://rfxn.github.io/copyfail/) [![Latest release](https://img.shields.io/github/v/release/rfxn/copyfail?label=release&color=22d3ee&labelColor=09090b)](https://github.com/rfxn/copyfail/releases/latest) [安装](#install) · [审计](#audit-the-host) · [纵深防御](#defense-in-depth-where-this-rung-carries-weight-on-its-own) · [子包](#subpackages) · [验证签名](#verifying-signatures)
## 安装 ``` sudo curl -sSL https://rfxn.github.io/copyfail/copyfail.repo \ -o /etc/yum.repos.d/copyfail.repo sudo dnf install -y afalg-defense ``` 一个 repo 文件即可适用于 EL8/EL9/EL10(dnf 会根据主机替换 `$releasever`/`$basearch`)。RPM 包经过 GPG 签名;dnf 在首次使用时会导入公钥——请在出现提示时交叉比对指纹: ``` 6001 1CDC EA2F F52D 975A FDEE 6D30 F32C D5E8 0F80 ``` 仅安装审计工具(无 `LD_PRELOAD`,适用于关键在线基础设施): ``` sudo dnf install -y afalg-defense-auditor ``` ## 激活 shim shim 已安装但**不会自动启用**。在 `%post` 阶段直接修改 `/etc/ld.so.preload` 会在任何升级失败时导致主机变砖——因此激活过程需要运维人员显式操作: ``` sudo /usr/sbin/copyfail-shim-enable # smoke-tests, then writes /etc/ld.so.preload sudo /usr/sbin/copyfail-shim-disable # reverses it ``` 启用辅助程序会先执行 `LD_PRELOAD=$shim /bin/true`;如果无法加载该 .so 文件,辅助程序将拒绝更新配置文件,以免将您锁定在外。 ## 同时黑名单 AF_ALG 模块(在可加载的情况下) 本软件包还附带了一个门槛同样极低的缓解措施:一个 `modprobe` drop-in 配置,可在内核层面切断 `algif_aead`、`authenc` 和 `authencesn`。当您的内核将 AF_ALG 作为可加载模块暴露时(大多数主线内核都是如此),这**与 shim 叠加使用**,且应受到同等重视。shim 在 libc 层阻断所有用户态调用者;而黑名单则彻底移除了内核攻击面。机制不同,但对运维人员来说都只需执行一行命令。 ``` # 决定黑名单在此内核上是否生效。 ls /sys/module/algif_aead 2>/dev/null && echo "modular - blacklist effective" \ || echo "builtin or absent - shim is your primary defense" grep -E 'ALG_USERMODE|CRYPTO_USER_API' /boot/config-$(uname -r) 2>/dev/null # =m -> modular(以黑名单为主) =y -> builtin(以 shim 为主) # 如果是 modular,请在 /etc/modprobe.d/ 中放入黑名单,并卸载 # 所有已驻留的模块。CVE-2026-31431 链是位于底部的 trio; # algif_* 系列是为了常规的 AF_ALG 卫生而添加的。 sudo tee /etc/modprobe.d/99-no-afalg.conf >/dev/null <<'EOF' install af_alg /bin/false install algif_aead /bin/false install algif_skcipher /bin/false install algif_hash /bin/false install algif_rng /bin/false install authenc /bin/false install authencesn /bin/false EOF sudo rmmod algif_aead authenc authencesn 2>/dev/null || true ``` (该软件包也将此文件附带在 `/usr/share/doc/afalg-defense/examples/no-afalg-modprobe.conf` 中——内容相同,如果您希望保留审计轨迹,可以将其复制到相应位置。)只要内核允许,请**同时**部署 shim 和黑名单——只需两条 `sudo` 命令即可获得双重保障。 ## 验证 ``` python3 -c 'import socket; socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)' # 预期:PermissionError [Errno 1] Operation not permitted ``` 被阻断的尝试会记录到 `auth.priv`: ``` no-afalg[12345]: blocked AF_ALG (domain=38) via socket uid=0 euid=0 pid=12345 ``` ## 审计主机 ``` sudo copyfail-local-check # human-readable, only flags non-OK sudo copyfail-local-check --json # SIEM ingestion (posture.verdict) sudo copyfail-local-check --emit-remediation # bash script of suggested fixes ``` 设计上为只读:仅通过 `mkdtemp()` 哨兵文件进行写入,从不修改 `/usr/bin` 或 `/etc`,以非特权身份运行(部分检查在无 root 权限时会优雅降级)。五大类别:`ENV`、`KERNEL`、`MITIGATION`、`HARDENING`、`DETECTION`。 退出码:`0` 安全 · `2` **存在漏洞 (VULN)**(无用户态缓解措施) · `3` 存在漏洞但已缓解 · `4` 仅有安全加固建议。 ## 移除 ``` sudo /usr/sbin/copyfail-shim-disable sudo dnf remove afalg-defense afalg-defense-shim afalg-defense-auditor ``` `%preun` 在完全卸载时也会作为安全网清除 `/etc/ld.so.preload`,但先进行禁用可使操作过程更加透明。 ## 防护范围 `AF_ALG` 的 `authencesn(hmac(sha256),cbc(aes))` AEAD 路径在解密时错误计算了输出长度,向用户态返回了比实际经过身份验证的字节数更多的数据。当该解密操作的目标是一个从 SUID 二进制文件或特权配置文件的页缓存拼接而来的管道时,内核会将攻击者控制的字节写入干净的页缓存页中——这对后续的所有读取者(包括通过 `execve()` 执行 `/usr/bin/su`)都是可见的。**磁盘文件没有任何更改**;这种破坏仅存在于 RAM 中,直到页面被驱逐。 这构成了一个本地权限提升原语,不需要攻击者加载内核模块(相关的加密模块在大多数发行版上会被 `socket(AF_ALG, ...)` 自动加载),并且**不会在磁盘上留下任何取证痕迹**。 ## 纵深防御:此防御层的独立价值所在 针对 AF_ALG 类漏洞共有五层防御,且每一层都有其失效场景。本软件包的意义在于,击败其上层防御的条件**与击败 shim 的条件并不相同**——这正是使 shim 成为可行的主要防御手段,而不仅仅是备份的原因。 | 级别 | 失效场景 | shim 在此处的作用 | |---|---|---| | 1. 内核补丁 (厂商) | EL7 已停止维护 (EOL);EL8/EL9/EL10 补丁发布通常落后漏洞披露数天至数周;在漏洞被高频利用的时间窗口内,生产环境可能无法立即重启 | **无需重启即可填补时间窗口。** 热安装,无需触碰内核 | | 2. 针对 `algif_aead` / `authenc` / `authencesn` 的 `modprobe` 黑名单 | 仅当这些模块作为**可加载模块**(而非内建)且在启动早期尚未驻留时有效。**在模块化内核上(大多数标准主线内核),这是与 shim 叠加使用的、门槛同样极低的主要防御手段**。当 `algif_aead` 是内建的(RHEL 默认)时,此措施无效 | **在内建加密算法的内核上接管防御**——每个用户态调用者无论内核如何暴露 AF_ALG,都必须经过 libc 的 `socket(2)` | | 3. systemd `RestrictAddressFamilies=~AF_ALG` | 仅能覆盖应用该限制后由 systemd 启动的服务。无法涵盖 **cron 任务、sshd 登录 shell、带有独立 pid 1 的容器负载**,以及任何在应用限制之前启动的进程 | **全局生效。** `/etc/ld.so.preload` 适用于所有动态链接的进程,无论由哪个 init 系统启动 | | 4. **`LD_PRELOAD` shim (本软件包)** | 静态编译的二进制文件;直接发起 `syscall` 指令的进程;SUID 二进制文件(内核会在安全执行时剥离 `LD_PRELOAD`) | (见右列的覆盖范围) | | 5. seccomp 过滤器 (按单元 / 容器运行时) | 按服务生效。运维操作成本高:每个单元/运行时都需要显式配置策略 | **一个 .so 文件 + 一行 ld.so.preload 配置**即可覆盖整个主机 | shim 自身失效的场景——静态二进制文件、直接使用 `syscall` 指令、SUID 剥离——属于**攻击者工程领域**。而其他层级失效则发生在**常规运维现实中**:厂商尚未发布补丁、内核内建了加密模块、威胁面包含 cron 任务等。这种不对称性正是优先部署此防御层的理由。 ### 适用场景:当此方案作为主要防御手段时 - 厂商内核补丁尚未发布(零日漏洞窗口)。 - 补丁已发布,但您*现在*无法立即重启主机。 - 内核内建了 `algif_aead`(导致 `modprobe` 黑名单无效)。 - 您的威胁面包含 systemd 之外的任何事物—— cron、登录 shell、容器负载,以及任何继承自应用限制前单元的进程。 - 您没有足够的运维精力为每个守护进程编写针对特定服务的 seccomp 策略。 审计工具会针对运行中的主机对这五个层级进行评估,并告知您哪些已启用、哪些已过期、哪些可被绕过——这样您就可以在后续可用时补充额外的防御措施,而不会忽略当前真正起支撑作用的机制。 ## shim 刻意不做之事 它不会封装 `syscall(2)`。无条件读取六个 `long` 类型的可变参数属于未定义行为,而且它能拦截的绕过方式(`syscall(SYS_socket, AF_ALG, ...)` 和内联汇编的 `syscall` 指令)从根本上无法从用户态阻断。请配合 seccomp 或内核补丁来应对该攻击面。 ## 子包 | 软件包 | 架构 | 内容 | |---|---|---| | `afalg-defense` | x86_64 | 元软件包 —— 拉取 shim + 审计工具 | | `afalg-defense-shim` | x86_64 | `/usr/lib64/no-afalg.so` + `copyfail-shim-{enable,disable}` | | `afalg-defense-auditor` | noarch | `/usr/sbin/copyfail-local-check` (Python,仅依赖标准库,只读) | 针对不同 EL 版本的二进制 RPM 包是分别根据各自发行版的 glibc 独立编译的(EL8:2.28 拆分版 `libdl`;EL9/EL10:2.34+ 合并版 `libdl`)。**请勿跨 EL 版本混装。** 直接下载链接 + sha256 校验和: [rfxn.github.io/copyfail](https://rfxn.github.io/copyfail/#direct-downloads)。 ## 验证签名 1.0.1 及更高版本由 **Copyfail 项目签名密钥** 签名。 `.repo` 文件强制启用了 `gpgcheck=1`(针对每个 RPM)和 `repo_gpgcheck=1`(对元数据使用 detached 签名 `repomd.xml.asc`)——因此原生的 `dnf install` 即可自动完成端到端验证。 ``` fingerprint: 6001 1CDC EA2F F52D 975A FDEE 6D30 F32C D5E8 0F80 uid: Copyfail Project Signing Key key file: https://rfxn.github.io/copyfail/RPM-GPG-KEY-copyfail ``` 带外验证: ``` curl -sSL https://rfxn.github.io/copyfail/RPM-GPG-KEY-copyfail \ | sudo rpm --import /dev/stdin rpm -K afalg-defense-1.0.1-1.el9.x86_64.rpm # 预期:digests signatures OK ``` ## 审计工具 JSON 结构 `--json` 会输出一个结构化对象,SIEM/仪表盘可直接摄取。核心内容是 `posture.verdict`;请使用该字段,而不是供人阅读的报告。 ``` { "posture": { "verdict": "vulnerable_kernel_userspace_mitigated", "layers": { "kernel_patched": "missing", "af_alg_unreachable": "missing", "modprobe_blacklist": "missing", "ld_preload_shim": "ok", "systemd_restriction": "missing", "user_service_dropin": "missing", "seccomp_runtime": "skipped", "auditd_running": "ok", "audit_rule_af_alg": "ok" } } } ``` `verdict` 可选值为:`patched`、`kernel_likely_safe`、`inconclusive`、`vulnerable_kernel_userspace_mitigated`、`vulnerable`。此设计的初衷是让集群管理控制台能够直接呈现每台主机的安全状态行,而无需基于原始检查重新实现判定逻辑。 `--emit-remediation` 会打印一个汇总了各项检查修复建议的 bash 脚本。输出默认**完全注释**;请在粘贴前仔细审查每一个代码块(修改 suid 二进制文件的权限、`modules_disabled` sysctl 参数、modprobe 黑名单均依赖于特定安全策略或需要重启才能撤销)。 ## 为什么进行这些检查? 审计工具是根据攻击链的层级构建的,而不是为了应付核对清单。每个类别都在回答关于主机的某个具体问题: - **`KERNEL`** —— 原语是否真的可达? AF_ALG socket 打开、密码算法可用性、`algif_aead` setsockopt、实时触发探测(唯一能产生明确 `VULN` 结果的检查)。 - **`MITIGATION`** —— 如果内核存在漏洞,当前是否有机制阻止该漏洞被利用?`/etc/ld.so.preload` 内容、shim 实时阻断测试、`modprobe` 黑名单、`/proc/modules` 真实状态、systemd `RestrictAddressFamilies`、drop-in 配置相对于运行中守护进程的新鲜度、seccomp 过滤器状态。 - **`HARDENING`** —— 如果缓解措施失效,爆炸半径有多大?SUID 清单、页缓存与 `O_DIRECT` 一致性抽样(稳定的差异是一个潜在的 IOC)、用于非 SUID 提权的 `getcap -r`。 - **`DETECTION`** —— 如果有人尝试利用,我们能知道吗?`auditd` 是否在运行且包含覆盖 `socket(38)` 的规则,`auth.priv` 和 `audit.log` 中是否存在近期的 IOC 信号。 - **`ENV`** —— 上下文:内核、发行版、glibc、root 状态。预先显示“跳过”的原因,以免一次无实际帮助的运行被误认为是一次安全通过的运行。 ## 从源码构建 `no-afalg.c` 是单文件,无需构建系统。已在 EL7 (gcc 4.8 / glibc 2.17)、EL8 (gcc 8.5 / glibc 2.28)、EL9 (gcc 11.5 / glibc 2.34) 和 EL10 (gcc 14 / glibc 2.39) 上测试通过。仅支持 x86_64。 ``` gcc -shared -fPIC -O2 -Wall -Wextra \ -o /usr/lib64/no-afalg.so no-afalg.c -ldl echo /usr/lib64/no-afalg.so > /etc/ld.so.preload ``` 从已发布的 SRPM 重新构建 RPM(在您自己的签名下): ``` mock -r centos-stream+epel-9-x86_64 --rebuild \ https://github.com/rfxn/copyfail/releases/download/v1.0.1/afalg-defense-1.0.1-1.el9.src.rpm ``` spec 文件位于 `packaging/afalg-defense.spec`。 ## 限制 - **仅支持 x86_64。** `AF_ALG` 常量是通用的,但 `LD_PRELOAD` shim 包含架构断言,且触发探测的结构布局仅在 x86_64 上经过测试。欢迎提交 arm64 补丁。 - 用户态 shim 对静态二进制文件和直接使用 syscall 指令的调用者无效(参见上文“shim 刻意不做之事”)。 - `modprobe` 黑名单不会卸载已驻留的模块。如果在编辑黑名单后 `/proc/modules` 显示它们仍然存在,您需要重启或执行 `rmmod`。 - 审计工具的触发探测仅对其自身的哨兵文件具有*破坏性*——它不会破坏任何您会注意到的内容。然而,如果 `algif_aead` 及相关模块尚未加载,它确实会短暂加载它们(这正是其目的所在)。 ## 许可证 GPL v2。详见 `LICENSE`。 [rfxn.com](https://www.rfxn.com/) | 诞生于生产环境 | Ryan MacDonald
标签:0day挖掘, AEAD, AF_ALG, authencesn, CentOS, Copy Fail, CVE-2026-31431, EL10, EL8, EL9, LD_PRELOAD, RHEL, Root权限, RPM, SUID, Web报告查看器, 主机安全态势, 代理, 内存破坏, 内存页缓存污染, 内核安全, 内核漏洞, 子域名枚举, 安全防护, 无文件攻击, 本地提权, 漏洞缓解, 系统安全, 纵深防御, 网络安全, 逆向工具, 隐私保护