本仓库包含 Linux algif_aead / authencesn 页缓存 scratch-write 漏洞
CVE-2026-31431 的检测器和 PoC。
披露文章:https://xint.io/blog/copy-fail-linux-distributions
仅可在你拥有或已获得明确授权的主机上使用。检测器是无破坏性的,只操作临时目录中的 sentinel 文件;PoC 和 LPE 会修改内存中的页缓存状态,属于真实的本地提权技术,未授权运行通常是违法行为。
algif_aead 会以原地方式执行 AEAD 操作,即 req->src == req->dst。当输入数据通过 splice() 从普通文件送入时,目标 scatterlist 中会包含该文件的页缓存页面引用,导致内核可能写入文件的页缓存副本。
authencesn(hmac(sha256),cbc(aes)) 会把 AAD 中 seqno_lo 字段(AAD 第 4 到 7 字节)做一次 4 字节 scratch write。结合上述原地 AEAD 和 splice() 路径后,攻击者可以让这 4 字节落到可读文件的页缓存页面中。
该修改不会写回磁盘,只影响当前内核页缓存。因此磁盘上的文件内容不变,但共享该页缓存的读取者会看到被污染后的内容。/etc/passwd 和 /usr/bin/su 这类 world-readable 文件都可能成为目标。
需要本机已安装 Rust 工具链和 Cargo。
编译所有 Rust binary:
cargo build --release --bins
编译完成后会生成:
target/release/cve_2026_31431_detector
target/release/cve_2026_31431_poc
仓库中如需提交预编译文件,请放在:
dist/linux-x86_64/cve_2026_31431_detector
dist/linux-x86_64/cve_2026_31431_poc
dist/linux-x86_64/SHA256SUMS
不要提交整个 target/ 目录;该目录包含 Cargo 中间产物和本机缓存。
只编译无破坏检测器:
cargo build --release --bin cve_2026_31431_detector
只编译 poc.py 的 Rust 版本:
cargo build --release --bin cve_2026_31431_poc
推荐使用 Rust 无破坏检测器:
./target/release/cve_2026_31431_detector
echo $?
也可以直接通过 Cargo 运行:
cargo run --release --bin cve_2026_31431_detector
echo $?
Python 检测器用法:
python3 test_cve_2026_31431.py
echo $?
退出码含义:
| 退出码 | 含义 |
|---|---|
0 | 未检测到漏洞,或前置条件不满足,例如 AF_ALG / authencesn 不可用。 |
2 | 检测到易受 CVE-2026-31431 影响。 |
1 |
常见输出判断:
检测器执行的操作:
AF_ALG 和 authencesn(hmac(sha256),cbc(aes)) 是否可用。sendmsg 发送 AAD,并把 AAD 的 seqno_lo 设置为 marker PWND。splice() 把 sentinel 文件页缓存页面送入 AF_ALG op socket。recv() 驱动算法执行。检测器不会修改 /usr/bin/su、/etc/passwd 或其他系统文件。临时 sentinel 文件会在退出时删除。
Rust 版 poc.py:
./target/release/cve_2026_31431_poc
或:
cargo run --release --bin cve_2026_31431_poc
注意:该 PoC 会按 poc.py 的逻辑打开 /usr/bin/su,通过漏洞原语污染它的页缓存副本,然后执行 su。这不是无破坏检测流程,只应在授权测试环境中运行。
python3 exploit_cve_2026_31431.py
python3 exploit_cve_2026_31431.py --shell
该脚本会查找当前用户在 /etc/passwd 中的 UID 字段,并尝试把页缓存中的 UID 改为 0000。磁盘上的 /etc/passwd 不会被修改,但系统进程读取页缓存时可能看到被污染后的内容。
限制条件:
1000 到 9999。nscd、sssd、systemd-userdbd,可能掩盖 /etc/passwd 的页缓存变化。/etc/passwd 页缓存需要在 patch 和执行 su 之间保持存在。清理页缓存:
python3 -c "import os; fd=os.open('/etc/passwd', os.O_RDONLY); os.posix_fadvise(fd, 0, 0, os.POSIX_FADV_DONTNEED); os.close(fd)"
如果已经获得 root shell,也可以执行:
echo 3 > /proc/sys/vm/drop_caches
重启也会清除页缓存状态。
在发行版内核修复前,可以禁用 algif_aead:
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null
应用缓解后,检测器通常应输出 检测结论:未发现漏洞,并说明触发前置条件不满足,退出码为 0。
上游修复思路是把 AEAD 操作从原地处理恢复为非原地处理,避免页缓存页面进入可写 destination scatterlist。
| 文件 | 说明 |
|---|
test_cve_2026_31431.py | Python 无破坏检测器。只操作临时 sentinel 文件,不触碰系统文件。 |
src/main.rs | Rust 无破坏检测器。检测逻辑和退出码与 Python 检测器一致。 |
src/bin/poc.rs | poc.py 的 Rust 版本。会污染 /usr/bin/su 的页缓存并执行 su。 |
poc.py | Python PoC。 |
exploit_cve_2026_31431.py | Python LPE。通过污染 /etc/passwd 页缓存尝试获得 root shell。 |
| 测试过程出错,结果不能作为漏洞判断依据。 |
| 输出 | 结论 |
|---|
检测结论:未发现漏洞 | 未检测到漏洞,或触发前置条件不满足。 |
检测结论:存在 CVE-2026-31431 漏洞 | marker PWND 成功落入 spliced 页缓存页面,存在漏洞。 |
检测结论:存在疑似 CVE-2026-31431 漏洞 | 页缓存被修改,即使 marker 没落到预期位置,也应视为受影响。 |
测试过程出错,无法判断是否存在漏洞 | 检测失败,退出码为 1,需要根据错误信息排查后重新运行。 |