立即修补您的内核:732字节Python rootkit,破解自2017年以来的所有发行版。
Patch Your Kernel NOW: 732byte Python rootkit, cracks all distros since 2017

原始链接: https://github.com/rootsecdev/cve_2026_31431

## CVE-2026-31431: Linux 内核权限提升 Linux 内核的 `algif_aead` 模块存在本地权限提升 (LPE) 漏洞 (CVE-2026-31431),具体位于 `authencesn` 算法 (hmac(sha256), cbc(aes)) 中。该漏洞于 2026 年 4 月 29 日披露,允许非特权用户破坏内核页面缓存,从而可能获得 root 权限。 当使用 `splice()` 将数据从普通文件输入到 AEAD 操作时,会发生此漏洞。`authencesn` 随后对目标页面缓存执行小规模的就地写入,从而破坏文件的缓存内容。重要的是,磁盘上的文件保持不变,这使得检测变得困难。 利用方法是破坏页面缓存中的 `/etc/passwd` 文件,将用户的 UID 更改为 0,然后使用 `su` 获取 root shell。提供了 Python 脚本 (`test_cve_2026_31431.py` 用于检测,`exploit_cve_2026_31431.py` 用于利用) 以进行测试和利用。 受影响的内核包括包含提交 72548b093ee3 (于 2017 年引入) *且未* 撤销上游补丁的内核。缓解措施包括禁用 `algif_aead` 模块或应用上游补丁,该补丁将恢复到非就地 AEAD 操作。 **重要提示:** 仅在您拥有或已获得明确评估权限的系统上使用这些工具。未经授权的使用是非法的。

Hacker News 新闻 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 立即修补你的内核:732字节Python rootkit,自2017年以来破解所有发行版 (github.com/rootsecdev) 7点 由 cednore 44分钟前 | 隐藏 | 过去 | 收藏 | 2评论 帮助 Bender 22分钟前 | 下一个 [–] 已验证修复在 7.0.2-2-cachyos 来自 PoC [1][1] - https://copy.fail/#exploit 回复 TacticalCoder 31分钟前 | 上一个 | 下一个 [–] 相关的Debian CVE追踪器:https://security-tracker.debian.org/tracker/CVE-2026-31431 回复 考虑申请YC 2026年夏季批次!申请截止至5月4日 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请YC | 联系 搜索:
相关文章

原文

Detector and proof-of-concept LPE for the Linux algif_aead / authencesn page-cache scratch-write bug disclosed 2026-04-29.

Disclosure writeup: https://xint.io/blog/copy-fail-linux-distributions

Use only on hosts you own or are explicitly engaged to assess. The LPE modifies in-memory state (page cache) but the technique is real privilege escalation — running it on systems without authorization is illegal in most jurisdictions.

algif_aead runs AEAD operations in-place (req->src == req->dst). When the source data is fed in via splice() from a regular file, the destination scatterlist contains references to the file's page-cache pages — i.e. the kernel will write into them. The authencesn(hmac(sha256), cbc(aes)) algorithm then performs a 4-byte "scratch" write of the AAD's seqno_lo field (bytes 4–7 of the sendmsg-supplied AAD) into that destination, corrupting the page-cache copy of the file.

Because the on-disk file is never modified, there is no on-disk signature; the corruption is observed only by readers that share the page cache. /etc/passwd and /usr/bin/su are both world-readable, so an unprivileged local user can corrupt the running kernel's view of either.

Affected: kernels carrying commit 72548b093ee3 (in-place AEAD, 2017) without the upstream revert. The disclosure confirmed Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 14.3, and SUSE 16, but the underlying primitive predates that range.

File Purpose
test_cve_2026_31431.py Non-destructive detector. Operates on a sentinel file in a temp dir; never touches system binaries.
exploit_cve_2026_31431.py LPE. Flips the running user's UID to 0 in /etc/passwd's page cache, then invokes su for a root shell.

Both scripts are pure Python 3.10+ stdlib.

# 1. Detect
python3 test_cve_2026_31431.py
#   exit 0 = not vulnerable, 2 = vulnerable, 1 = test error

# 2. Exploit (interactive — su will prompt for your own password)
python3 exploit_cve_2026_31431.py --shell
python3 test_cve_2026_31431.py

What it does:

  1. Confirms AF_ALG and the authencesn(hmac(sha256),cbc(aes)) algorithm are reachable from an unprivileged process.
  2. Creates a 4 KiB sentinel file in a temp directory, populates the page cache.
  3. Sends 8 bytes of AAD inline via sendmsg+cmsg with seqno_lo set to the marker PWND, then os.splice()s 32 bytes of the sentinel's page-cache page into the AF_ALG op socket.
  4. Calls recv() to drive decryption. The auth check fails with EBADMSG; the scratch write fires regardless.
  5. Re-reads the file (page cache, not disk) and looks for the marker.

Output classes:

  • Precondition not metAF_ALG or authencesn unavailable. Exit 0.
  • VULNERABLE to CVE-2026-31431 — marker PWND landed in the spliced page. Exit 2.
  • Page cache MODIFIED via in-place AEAD splice path — the page was written to but the marker did not land at the expected position. Treat as vulnerable. Exit 2.
  • Page cache intact — patched. Exit 0.

The detector never touches /usr/bin/su, /etc/passwd, or any other file outside the temp directory it creates, and that file is removed on exit.

python3 exploit_cve_2026_31431.py            # patch only, print next steps
python3 exploit_cve_2026_31431.py --shell    # patch and exec `su <user>`

What it does:

  1. Looks up the running user's UID line in /etc/passwd and finds the byte offset of the 4-character UID field.
  2. Issues one write4 against that offset, replacing the UID with 0000.
  3. Calls pwd.getpwnam(user) to confirm libc now reports UID 0.
  4. With --shell, execvp("su", ["su", user]). Enter your own password. PAM validates against /etc/shadow (untouched), then setuid(getpwnam(user).pw_uid) lands at 0.
  • Running user has a 4-digit UID (1000–9999). 1- to 3-digit UIDs require multi-shot writes — extend write4 accordingly.
  • No NSS caching daemon (nscd, sssd, systemd-userdbd) is masking /etc/passwd reads. If getpwnam still returns the real UID after the patch, restart or bypass the cache, or pick a different user.
  • /etc/passwd page must remain in cache between the patch and the su exec. In practice this is reliable on any system with normal memory pressure.

The on-disk /etc/passwd is unchanged.

Dry-run (exploit_cve_2026_31431.py without --shell) auto-evicts the corrupted page on exit via POSIX_FADV_DONTNEED, so UID→name lookups go back to normal immediately.

After --shell, the page is left corrupted until you clear it. While it is corrupted, anything resolving UID 1000 → name (e.g. ls, file managers, scp/sftp ownership checks) will fail or show numeric IDs. To clear:

# unprivileged - request page-cache eviction for /etc/passwd:
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)"

# from the root shell:
echo 3 > /proc/sys/vm/drop_caches

A reboot also clears it.

sendmsg([8-byte AAD], cmsg=[ALG_SET_OP=DECRYPT, ALG_SET_IV, ALG_SET_AEAD_ASSOCLEN=8],
        flags=MSG_MORE)
splice(target_fd, pipe_w, 32, offset_src=file_offset)
splice(pipe_r, op_fd, 32)
recv(op_fd)   # EBADMSG; scratch write has already landed

The 4 bytes from AAD positions 4–7 (seqno_lo) are written by authencesn into the destination scatterlist, which on this code path is the page-cache page we spliced from target_fd. The landing offset within the page corresponds to the offset_src we passed to splice().

Until the patched kernel reaches your distro:

sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null

After applying, test_cve_2026_31431.py should report Precondition not met and exit 0.

The upstream fix reverts in-place AEAD operations to out-of-place, keeping page-cache pages out of writable scatterlists.

联系我们 contact @ memedata.com