ctzisme/copyfail-guard

GitHub: ctzisme/copyfail-guard

一款零依赖的 Python CLI 工具,用于非侵入式检测 Linux 主机是否受 CVE-2026-31431「Copy Fail」提权漏洞影响,并提供临时缓解措施。

Stars: 1 | Forks: 0

# copyfail-guard [![PyPI](https://img.shields.io/pypi/v/copyfail-guard)](https://pypi.org/project/copyfail-guard/) [![Python](https://img.shields.io/pypi/pyversions/copyfail-guard)](https://pypi.org/project/copyfail-guard/) [![License](https://img.shields.io/pypi/l/copyfail-guard)](LICENSE) [![pylint](https://img.shields.io/badge/pylint-10.00%2F10-brightgreen)](https://pylint.readthedocs.io/) 一个零依赖的 Python CLI 工具,用于检查 Linux 主机是否暴露于 [CVE-2026-31431](https://copy.fail)("Copy Fail")**而不运行漏洞利用程序**。 当受影响的组件可作为内核模块加载时,它还可以应用保守的临时缓解措施。 支持 Debian/Ubuntu、RHEL/Rocky/AlmaLinux、Fedora 和 SUSE。 ``` pip install copyfail-guard copyfail-guard ``` ## 背景 CVE-2026-31431 是 `algif_aead`(AF_ALG AEAD 套接字)内核 接口中的一个逻辑漏洞,允许无权限的本地用户对任何可读文件的 页面缓存执行受控的 4 字节写入,从而实现 root 权限提升。 CVSS 7.8,自内核 4.14 起存在,已于 2026 年 4 月起在稳定版本中修复。 存在公开的漏洞利用代码,该漏洞已列入 CISA KEV。 ## 为什么不直接运行漏洞利用程序? 某些漏洞检查本质上等于"运行漏洞利用程序看看是否有效"。 这在生产主机上并不是一个好主意。 copyfail-guard 采用非漏洞利用方法。它不会尝试触发漏洞、 修改 setuid 二进制文件,或证明可利用性。相反,它检查主机状态 (内核版本、模块加载状态、modprobe 配置)并报告机器是否暴露。 ## 此工具的功能 | 子命令 | 操作 | |---|---| | `detect` | 将五个信号(内核版本、`/proc/modules`、`modules.builtin`、`modules.dep`、modprobe 配置)综合为六种裁决之一 | | `fix` | 原子化地写入 `install algif_aead /bin/false` modprobe 规则,并尝试卸载 `algif_aead` | | `reset` | 移除 `fix` 安装的 modprobe 规则(在升级到已修复内核后运行) | `fix` 刻意保持最小化——它**不会**调用你的包管理器。 永久修复需要通过发行版的正常更新机制升级内核。 ## 安装 ``` pip install copyfail-guard ``` 或者直接从检出的代码运行而不安装: ``` PYTHONPATH=src python3 -m copyfail_guard detect ``` ## 使用方法 ``` copyfail-guard [--json] [--dry-run] [--quiet] [detect | fix | reset] ``` ### detect(默认) ``` $ copyfail-guard [copyfail-guard] CVE-2026-31431 (Copy Fail) — VULNERABLE Distribution: Ubuntu 24.04.1 LTS (debian family) Kernel: 6.8.0-50-generic (branch 6.12, fixed at 6.12.85) Module: algif_aead — loaded as .ko Mitigation: none Recommended actions: 1. Apply mitigation now: sudo copyfail-guard fix 2. Update the kernel for a permanent fix: Update the kernel on this system to 6.12.85 or later (whatever your distribution ships once it has integrated the CVE-2026-31431 fix), then reboot. ``` ### fix 应用前始终使用 `--dry-run` 进行预览: ``` $ sudo copyfail-guard --dry-run fix [copyfail-guard] fix (dry-run) — OK [ ok ] Pre-flight checks (Linux, host, root) [skip] Would write modprobe blacklist [/etc/modprobe.d/cve-2026-31431-copyfail-guard.conf] [skip] Would attempt to unload algif_aead (not currently loaded) [algif_aead] [skip] Would append audit record [/var/log/copyfail-guard.log] $ sudo copyfail-guard fix [copyfail-guard] fix — OK [ ok ] Pre-flight checks (Linux, host, root) [ ok ] Wrote modprobe blacklist [/etc/modprobe.d/cve-2026-31431-copyfail-guard.conf] [ ok ] Unloaded algif_aead [algif_aead] [ ok ] Appended audit record [/var/log/copyfail-guard.log] Next step for a permanent fix: Update the kernel to a CVE-2026-31431-patched version using your distribution's normal update mechanism, then reboot. ``` 如果模块当前正在使用中,卸载步骤可能会失败。在这种情况下, 持久化的 modprobe 规则仍然可以成功安装,copyfail-guard 会将卸载失败报告为警告式操作记录,而不是 假装模块已被移除。 ### JSON 输出 `--json` 在 stdout 上输出结构化文档,适合 jq、Ansible 或 SOAR 管道: ``` $ copyfail-guard --json | jq .verdict "vulnerable" $ copyfail-guard --json | jq '{verdict, kernel: .kernel.patched_threshold}' { "verdict": "vulnerable", "kernel": "6.12.85" } ``` ## 退出码 | 代码 | 含义 | |---|---| | `0` | 安全——裁决为 `patched`、`mitigated` 或 `not_applicable`;或持久化修复步骤成功 | | `1` | 易受攻击——裁决为 `vulnerable` 或 `unmitigable_builtin` | | `2` | 错误——无法确定状态、拒绝前置条件,或持久化修复步骤失败 | ## 裁决 | 裁决 | 描述 | |---|---| | `patched` | 运行的内核处于或高于修复版本 | | `mitigated` | 内核存在漏洞,但 `algif_aead` 被 modprobe 配置阻止 | | `not_applicable` | 内核存在漏洞,但 `algif_aead` 在此系统上不存在 | | `vulnerable` | 内核存在漏洞,模块可加载,无缓解措施 | | `unmitigable_builtin` | `algif_aead` 已编译到内核镜像中——modprobe 缓解无效;需要升级内核 | | `unknown` | 无法解析内核版本或超出评估范围 | ## 移除缓解措施 升级到已修复内核后,使用 `reset` 子命令移除 `fix` 安装的 modprobe 规则: ``` $ sudo copyfail-guard --dry-run reset [copyfail-guard] reset (dry-run) — OK [skip] Would remove /etc/modprobe.d/cve-2026-31431-copyfail-guard.conf $ sudo copyfail-guard reset [copyfail-guard] reset — OK [ ok ] Removed /etc/modprobe.d/cve-2026-31431-copyfail-guard.conf Reboot to allow algif_aead to load again if needed. ``` `reset` 是幂等的——如果文件已不存在,它会以 "无事可做"消息退出 0。然后重启。 ## 注意事项 **容器。** `fix` 拒绝在容器内运行,因为 `/proc/modules` 反映的是主机内核,但容器无权加载或卸载模块。 直接在主机上运行 copyfail-guard。 **内置 `algif_aead`。** 某些内核将 `algif_aead` 直接编译到镜像中 (`CONFIG_CRYPTO_USER_API_AEAD=y`)。modprobe 缓解在此配置中无效; 唯一的修复方法是升级内核。`detect` 在这种情况下报告 `unmitigable_builtin`。运行 `fix` 仍会安装 modprobe 规则 (可阻止任何共存的的可加载副本加载),但内置 实例不受影响——内核升级和重启是唯一的真正解决方案。 **`blacklist` vs `install … /bin/false`。** 两种指令都阻止普通 自动加载,但 `install algif_aead /bin/false` 更强,因为它还 阻止普通的显式 `modprobe algif_aead` 调用。足够 权限的管理员仍然可以绕过 modprobe 策略,例如使用 低级模块加载工具或特殊 modprobe 标志。copyfail-guard 始终 安装更强的形式。如果你的系统已有普通的 `blacklist` 指令,该工具会报告 `mitigated` 但会发出说明建议升级。 **SELinux/AppArmor。** 在 RHEL 上写入 `/etc/modprobe.d/` 通常继承 父目录的 `system_u:object_r:modules_conf_t:s0`,因此通常不需要 手动重新标记 copyfail-guard 写入的文件。 **initramfs。** `algif_aead` 通常不包含在主流 发行版的启动镜像中,因此 copyfail-guard 在安装 modprobe 规则后 不会运行 `update-initramfs -u` 或 `dracut -f`。如果你的发行版或本地 构建在 initramfs 中包含 `algif_aead`,请遵循你的发行版的 内核/模块指南。 ## 许可证 Apache 2.0——请参阅 [LICENSE](LICENSE)。
标签:AF_ALG, algif_aead, Copy Fail, CVE-2026-31431, modprobe, Python CLI, 内核模块, 内核漏洞, 反取证, 多发行版支持, 安全渗透, 安全评估, 安全资源, 库, 应急响应, 权限提升防护, 漏洞缓解, 系统加固, 逆向工具, 零依赖