Skip to content
KitploitKITPLOIT
工具博客
Log in
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-31431-Analysis-and-Fix — Linux 内核 CVE-2026-31431(Copy Fail)的深入技术分析,这是一种通过 AF_ALG 就地 scatterlist 漏洞实现的本地权限提升,包括根本原因、利用路径和补丁提交指南。 | Kitploit
工具/GitHubGitHub/abdelkabirouadoukou/cve-2026-31431-analysis-and-fix
漏洞分析漏洞利用二进制分析论文与研究学习与教育精选资源
GitHubabdelkabirouadoukou/cve-2026-31431-analysis-and-fix

CVE-2026-31431-Analysis-and-Fix

Linux 内核 CVE-2026-31431(Copy Fail)的深入技术分析,这是一种通过 AF_ALG 就地 scatterlist 漏洞实现的本地权限提升,包括根本原因、利用路径和补丁提交指南。

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
查看仓库
23410天前尚未审核
分享

CVE-2026-31431 “Copy Fail” — 技术深度剖析

严重性: CVSS 7.8(高危)

类型: 本地权限提升

引入版本: Linux 4.14(2017 年)

修复版本: 提交 a664bf3d603d

1. 背景

CVE-2026-31431 是 Linux 内核 algif_aead 模块中的一个本地权限提升漏洞——该模块是内核用户态加密 API(AF_ALG)的 AEAD 套接字接口。

该漏洞允许非特权用户利用 Linux 内核加密 API 中的地址族 AF_ALG,对页缓存执行受控的 4 字节写入,而页缓存承载着文件的内存副本。通过替换页缓存中可读可执行文件的内存副本中的代码,当任何特权进程随后运行该被篡改的文件版本时,攻击者即可提升用户权限。

与需要竞争条件的 Dirty Cow(CVE-2016-5195)不同,Copy Fail 是一个直线型逻辑缺陷。它无需竞争、重试或易崩溃的时序窗口即可触发。

2. 根本原因 — 2017 年的原地优化

2.1 变更内容

提交 72548b093ee3(“crypto: algif_aead - switch to in-place processing”)引入了一项优化,在 aead_recvmsg() 中设置 req->src == req->dst,从而省去了单独的输出缓冲区分配。

该优化导致 req->src 和 req->dst 指向一个合并的 scatterlist。因此,来自 splice() 调用的页缓存页面被错误地直接链接到可写的目标 scatterlist 中。

2.2 隐式不变量

内核的 AEAD API 定义了一个明确的输出契约:目标缓冲区接收 AAD || 明文,恰好为 assoclen + (cryptlen - authsize) 字节。API 中没有任何机制强制执行此契约,也没有任何文档将其列为要求。该设计假设每个 AEAD 算法都会将其写入限制在预期的目标范围内。但有一个算法并未如此。

3. 受影响文件

crypto/
├── algif_aead.c      ← 原地 scatterlist 缺陷(主要)
└── authencesn.c      ← 越界临时写入(触发点)

4. 漏洞代码

4.1 crypto/algif_aead.c — 原地赋值

/* 存在漏洞 — 2017 年后的原地路径 */
static int aead_recvmsg(struct socket *sock, struct msghdr *msg,
                        size_t ignored, int flags)
{
    /* ... */

    /*
     * 当用户态对文件调用 splice(2) 时,areq->tsgl 包含
     * 该文件的页缓存页面。将 dst = src 会将这些页缓存
     * 页面作为可写输出缓冲区交给加密引擎。
     */
    aead_request_set_crypt(req,
        areq->tsgl,   /* src */
        areq->tsgl,   /* dst — 相同指针;根本原因 */
        areq->cryptlen, iv);
}

4.2 crypto/authencesn.c — 越界临时写入

authencesn 模板是 IPsec 用于扩展序列号(ESN)支持的 AEAD 包装器。IPsec 使用 64 位序列号,分为高半部分(seqno_hi,AAD 的第 0–3 字节)和低半部分(seqno_lo,第 4–7 字节)。线上格式仅携带 seqno_lo;seqno_hi 是隐式的。

/* crypto/authencesn.c — 超出输出边界的临时写入 */
static int crypto_authenc_esn_decrypt(struct aead_request *req)
{
    /* ... */

    /*
     * authencesn 将 seqno_hi 临时存储在 req->dst 中
     * 偏移量 (assoclen + cryptlen) 处 — 超出合法输出
     * 区域一个字。
     *
     * 正常操作下:命中内核拥有的内存。
     * 使用原地 scatterlist 时:命中页缓存页面。
     */
    scatterwalk_map_and_copy(&seqno_hi,
        req->dst,
        req->assoclen + req->cryptlen,   /* 越界偏移量 */
        sizeof(seqno_hi),                /* 4 字节 */
        1 /* 写入 */);

    /* authencesn 在失败路径上不会恢复这些字节 */
}

5. 修复方案

上游修复: 提交 a664bf3d603d — 回滚 2017 年的优化。

5.1 crypto/algif_aead.c — 分离的 scatterlist

/* 已修复 — 分离的 src 和 dst */
aead_request_set_crypt(req,
    areq->tsgl,   /* src — 可能包含页缓存页面;只读 */
    areq->rsgl,   /* dst — 新分配的内核缓冲区;可写 */
    areq->cryptlen, iv);

效果: 页缓存页面保留在 src 中,加密引擎仅对其进行读取。authencesn 在 assoclen + cryptlen 处的临时写入现在落入进程拥有的内核分配缓冲区中。任何页缓存页面都无法从写入路径到达。

6. 利用路径

以下描述了 4 字节写入如何实现完全权限提升。

步骤操作
1打开一个配置为 authencesn(hmac(sha256),cbc(aes)) 的 AF_ALG 套接字
2将可读的 setuid 二进制文件(例如 /usr/bin/sudo)splice() 到套接字中 — 这会将其页缓存页面放入 areq->tsgl
3精心构造 assoclen + cryptlen,使临时写入偏移量与二进制文件缓存映像中的目标字节对齐
4调用 recvmsg() — 触发解密路径,authencesn 将 4 个攻击者控制的字节写入页缓存
5磁盘上的文件保持不变;完整性检查器、inotify 和 inode 时间戳均不受影响
6随后对该二进制文件的任何执行都会映射已修改的页缓存页面 — 修补后的代码以 euid=0 运行

该写入最终落在内存中被拼接文件缓存数据中,完全绕过了文件的权限机制。

7. 向 LKML 提交补丁

7.1 识别维护者

./scripts/get_maintainer.pl crypto/algif_aead.c
# Herbert Xu <[email protected]>
# [email protected]

7.2 验证补丁

./scripts/checkpatch.pl 0001-crypto-algif_aead-revert-inplace.patch

7.3 提交信息格式

crypto: algif_aead - restore separate src/dst scatterlists in recvmsg

Commit 72548b093ee3 ("crypto: algif_aead - switch to in-place
processing") set req->src == req->dst inside aead_recvmsg(). When
the caller uses splice(2), the source scatterlist contains page
cache pages of the spliced file. With the in-place optimization,
those same pages become the writable destination passed to the
AEAD transform.

authencesn writes 4 bytes at offset (assoclen + cryptlen) into
req->dst as scratch space for Extended Sequence Number
rearrangement and does not restore them on the error path. With
page cache pages present in dst, this write bypasses the VFS
permission layer and corrupts the in-memory image of the spliced
file without modifying the on-disk inode.

An unprivileged local user can exploit this to overwrite
arbitrary bytes in the page cache of any readable setuid binary
and escalate privileges to root.

Restore separate src and dst scatterlists so that page cache
pages are confined to the read-only source path.

Fixes: 72548b093ee3 ("crypto: algif_aead - switch to in-place processing")
Cc: [email protected]  # 4.14+
Reported-by: Taeyang Lee <[email protected]>
Signed-off-by: Your Name <[email protected]>

7.4 通过 git send-email 发送

git send-email \
  [email protected] \
  [email protected] \
  [email protected] \
  0001-crypto-algif_aead-revert-inplace.patch

7.5 提交信息约定

元素用途
subsystem: file - verb phrase 主题必需格式;不超过 72 个字符
Fixes: <sha> ("original title")触发自动稳定版回溯工具
Cc: [email protected]标记补丁以进行 LTS 分支回溯
Reported-by:归功于发现者
Signed-off-by:开发者来源证书 — 必需

8. 受影响版本与缓解措施

受影响的内核涵盖 Linux 4.14 至 7.0-rc、所有 6.18.22 之前的 6.18.x 以及 6.19.12 之前的 6.19.x。

临时缓解措施(大多数系统无需重启):

echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true

此变通方案不影响 dm-crypt/LUKS、kTLS、IPsec/XFRM、OpenSSL、GnuTLS、NSS 或 SSH。

9. 参考资料

  • Theori/Xint 公告:xint.io/blog/copy-fail-linux-distributions
  • NVD 条目:nvd.nist.gov/vuln/detail/CVE-2026-31431
  • 上游修复:提交 a664bf3d603d(主线)
  • 引入提交:72548b093ee3(Linux 4.14,2017 年)
下载工具