针对 CVE-2026-31431 Linux 内核 LPE 漏洞(Copy Fail)的检测规则、YARA 签名、auditd/Wazuh 规则和 MISP 事件模板。包括 IoC、缓解步骤和漏洞利用分析。
发布日期: 2026-04-30
CVSSv3: 7.8(高危)
类型: 本地权限提升(LPE)
子系统: Linux 内核 algif_aead / authencesn 加密模板
影响范围: Linux 内核 4.14 – 6.18.21(几乎自 2017 年以来的所有发行版)
参考资料:
CVE-2026-31431 是内核 4.14(2017 年)中引入的一个逻辑缺陷,源于三个独立变更的交集:
authencesn 模板(2011 年添加,用于 IPsec ESN 支持)会在其输出缓冲区边界之外写入 4 字节的临时数据。AF_ALG 在 2015 年获得了 AEAD 支持,允许用户空间通过 splice() 从页缓存文件提交数据。algif_aead.c 被优化为原地操作(req->src == req->dst),将活动页缓存页面放入可写的散列/收集列表(scatterlist)中。结果:无特权用户可以向内核页缓存中任意可读文件(包括 setuid 二进制文件和 /etc/passwd)的副本写入恰好 4 字节由攻击者控制的数据,而无需触碰磁盘上的文件。可用的 PoC 是一个 732 字节的 Python 脚本。无需竞态条件,无需针对特定发行版的偏移量。在 Ubuntu、RHEL、Amazon Linux 和 SUSE 上均稳定可靠。
Attacker opens AF_ALG socket (family 38, type 5) └─ Binds to "authencesn(hmac(sha256),cbc(aes))" └─ Sets SOL_ALG (279) options including key and authsize └─ Accepts a connection socket
Attacker opens target file (e.g., /etc/passwd) read-only └─ Uses splice() to feed page-cache pages into the AEAD socket's RX buffer └─ Sends crafted AAD via sendmsg() — bytes 4–7 of AAD = attacker-controlled write value
authencesn performs in-place decryption: └─ scatterwalk_map_and_copy writes seqno_lo into the chained page-cache page └─ recvmsg() returns an error (HMAC fails — expected), but the write already happened
Page-cache now contains attacker-modified copy of the file └─ Kernel executes from page-cache, not disk └─ On-disk file is UNCHANGED — file integrity tools see nothing
该PoC针对`/etc/passwd`:它找到当前用户UID字段的偏移量,并将其覆盖为`0000`,然后调用`su`获取root shell。
---
## 检测限制
> **在部署以下规则之前,请先阅读本节内容。**
该漏洞利用有两个特性,极大地限制了检测覆盖范围:
**1. 写入操作针对的是页缓存,而非文件系统。**
任何监控文件系统事件的检测工具——`inotify`、`fanotify`、AIDE、Tripwire、auditd路径监控——都**不会**观察到该修改。磁盘上的文件从未被写入。这意味着auditd路径监控中针对`/usr/bin/su`或`/etc/passwd`的`-p w`(写入)标志将不会捕获实际的漏洞利用写入。
**2. 该机制使用了合法的内核接口。**
`AF_ALG`套接字、`splice()`和`authencesn`都有合法用途(IPsec、内核自测试、sendfile风格的I/O)。检测必须关注这些原始操作的**组合**,而非孤立地看待任何一个,并且在运行IPsec或进行内核加密测试的系统上,预期会出现误报。
**检测能够捕捉到的内容:**
- `socket(AF_ALG, SOCK_SEQPACKET, 0)`系统调用
- 与上述相关的`splice()`系统调用,尤其是在访问setuid二进制文件附近
- PoC脚本本身(通过YARA)
- 进程内存或脚本文件中特定的`authencesn(hmac(sha256),cbc(aes))`算法字符串
**检测无法捕捉到的内容:**
- 实际的页缓存写入(内存中,无文件系统事件)
- 利用后对修改后的页缓存条目的使用(看起来像正常的`su`或`passwd`调用)
- 避开Python或特定算法字符串的变种
---
## 即时缓解措施
在部署检测规则之前,请在未打补丁的主机上应用此缓解措施:```bash
# Disable algif_aead kernel module — blocks the exploit primitive entirely
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
sudo rmmod algif_aead 2>/dev/null || true
验证缓解措施是否生效 使用官方检测器:```bash
python3 test_cve_2026_31431.py
> **注意:** `rmmod` 命令在模块未加载时会失败;这是可接受的。`modprobe.d` 配置可防止未来加载。此缓解措施对标准 TLS、SSH 或文件系统加密工作负载没有影响——它仅影响使用 `authencesn` 模板的具有扩展序列号的 IPsec,这在不属于专用 VPN 网关的情况外并不常见。
---
## YARA 规则
保存为 `cve_2026_31431.yar`
> **扫描范围:** 此规则旨在扫描磁盘上的或从内存转储中提取的 Python 脚本文件。它将匹配已知的 PoC 和相近变体。它不会检测系统调用级别的利用活动——请使用 auditd/Wazuh 规则进行检测。```yara
rule CVE_2026_31431_CopyFail_PoC_HighConfidence {
meta:
description = "High-confidence match: CVE-2026-31431 Copy Fail PoC or close variant"
author = "Detection Engineering"
reference = "https://xint.io/blog/copy-fail-linux-distributions"
cve = "CVE-2026-31431"
date = "2026-04-30"
severity = "High"
cvss = "7.8"
strings:
// Algorithm string unique to this exploit path — very high fidelity
$alg_full = "authencesn(hmac(sha256),cbc(aes))" ascii
// Specific socket call signature from PoC: AF_ALG=38, SOCK_SEQPACKET=5
$socket_call = "socket(38,5,0)" ascii
// SOL_ALG socket option (decimal 279)
$solalg = "setsockopt(279" ascii
// Hex key/iv payload written via setsockopt in PoC
$key_payload = "0800010000000010" ascii
// splice() usage in context of AEAD operations
$splice = "splice(" ascii
// Target indicators from PoC (page-cache corruption targets)
$target_passwd = "/etc/passwd" ascii
$target_su = "/usr/bin/su" ascii
// AF_ALG aead bind strings
$aead_bind = "\"aead\"" ascii
condition:
// High-confidence: unique algorithm string alone is sufficient
$alg_full
or
// Medium-confidence: socket primitive + option number
($socket_call and $solalg)
or
// Medium-confidence: splice into AEAD socket targeting a setuid path
($aead_bind and $splice and ($target_passwd or $target_su))
or
// PoC hex payload present alongside splice
($key_payload and $splice)
}
rule CVE_2026_31431_CopyFail_Mechanism {
meta:
description = "Behavioral: AF_ALG AEAD + splice combination suggestive of CVE-2026-31431 technique"
author = "Detection Engineering"
reference = "https://xint.io/blog/copy-fail-linux-distributions"
cve = "CVE-2026-31431"
date = "2026-04-30"
severity = "Medium"
note = "Higher false positive rate than HighConfidence rule — review matches in context"
strings:
$authencesn = "authencesn" ascii nocase
$af_alg_num = "socket(38" ascii
$sol_alg_num = "279" ascii
$splice = "splice(" ascii
condition:
($authencesn and $splice)
or
($af_alg_num and $sol_alg_num and $splice)
}
保存为 /etc/audit/rules.d/cve-2026-31431.rules
重新加载:```bash sudo augenrules --load
sudo auditctl -R /etc/audit/rules.d/cve-2026-31431.rules
(空)```bash
## ============================================================
## CVE-2026-31431 "Copy Fail" — Auditd Detection Rules
## ============================================================
## These rules capture the MECHANISM of the exploit (socket +
## splice syscalls) and correlated /etc/passwd access patterns.
##
## IMPORTANT: These rules will NOT detect the page-cache write
## itself — it is an in-memory operation with no filesystem
## event. File path watches (-w) on setuid binaries or
## /etc/passwd will not fire on the exploit write.
##
## Correlate rule hits across audit.key values to build signal:
## A hit on afalg_socket followed closely by a hit on
## splice_syscall from the same process is a strong indicator.
## ============================================================
## --- Core exploit primitive: AF_ALG socket creation ---
## Monitors socket(2) syscall where a0 = 0x26 (38 decimal = AF_ALG)
## This is the first step of the exploit chain.
-a always,exit -F arch=b64 -S socket -F a0=0x26 -k cve_2026_31431_afalg_socket
-a always,exit -F arch=b32 -S socket -F a0=0x26 -k cve_2026_31431_afalg_socket
## --- splice() syscall monitoring ---
## splice() is used to feed page-cache pages into the AEAD socket.
## NOTE: splice() is commonly used for sendfile-like operations.
## Correlate with cve_2026_31431_afalg_socket hits from the same PID.
-a always,exit -F arch=b64 -S splice -k cve_2026_31431_splice
-a always,exit -F arch=b32 -S splice -k cve_2026_31431_splice