ipv6_frag_escape: Linux 本地提权 - 可靠的容器/沙盒逃逸

Lobsters Hottest 工具

摘要

针对 Linux 本地提权和容器/沙盒逃逸的概念验证,利用内核中的 IPv6 分片漏洞,目标是 CentOS/RHEL 10。

<p><a href="https://lobste.rs/s/eihlve/ipv6_frag_escape_linux_lpe_reliable_jail">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/29 18:30

sgkdev/ipv6_frag_escape

来源:https://github.com/sgkdev/ipv6_frag_escape

IPV6_FRAG_ESCAPE

针对 CentOS / RHEL 10 的一个可靠的无特权容器/ jail 逃逸概念验证。它利用了 __ip6_append_data() 中现已修复的 IPv6 分片漏洞(上游通过 38becddc 关闭,无 CVE),这是一个 slab 内线性溢出,溢出到数据包自身头部对象尾部的 skb_shared_info。本 README 仅记录利用链,不涵盖触发过程。

作用域

  • 目标:CentOS / RHEL 10(内核 6.12.x,例如 6.12.0-242.el10)。
  • 起点:网络隔离容器内的无特权进程,可访问无特权用户命名空间。
  • 结果:在宿主机的初始命名空间和根文件系统中获得交互式 root shell。

说明

这是一个概念验证,刻意不做成即用型武器。故意省略了可靠性支撑:没有 per-CPU PCP 整理,没有跨缓存 SLUB 加固,skb 头部放置在一个共享且不太安静的缓存中。实际触发时,成功率足以证明链条的可行性,但仅此而已。适用范围仅限于 CentOS / RHEL 10。

要求

  • CONFIG_INIT_ON_ALLOC_DEFAULT_ON 关闭(RHEL / CentOS 默认)。该 PoC 在未初始化的 slab 字节中植入一个过期指针;若开启 init_on_alloc=1,该槽位会被清零,此特定技术只会导致内核崩溃(NULL 解引用)。这是该技术的局限性,而非漏洞本身:一个能覆盖那些内核的完整利用(采用不同技术)将在修复和 CVE 公开后发布。
  • 5 级分页(LA57,57 位线性地址)。页表遍历基于五级设计,启动检查会在没有此条件时拒绝运行。若使用四级 CPU 则需要重构遍历逻辑。
  • /sys/kernel/btf/vmlinux 存在且世界可读(RHEL / CentOS 默认如此)。

已测试的内核

发行版内核结果
CentOS Stream 106.12.0-242.el10root,容器逃逸
RHEL 106.12.0-228.el10httpd_t 上下文逃逸

利用链

  1. 从 slab 内溢出到自释放(self-UAF)。
    该漏洞使我们能控制 skb_shared_info 中单个 nr_frags 字节。释放路径(skb_release_data())会遍历 frags[0 .. nr_frags) 并对每个条目调用 put_page(),而 frags[] 从未初始化。我们通过受控的缓存重用,将一个指向 pipe 缓冲区页面的 struct page * 预植入该 slab 槽位,然后将 nr_frags 设为 1,这样在释放时会减少一个我们仍拥有的页面的引用计数。线性溢出变成了页面释放后重用(UAF)。溢出从未触及 frags[0],因此不需要与 spray 进行时序配合,这也是该技术容错性高的主要原因。

  2. 从页面 UAF 到脏页表(Dirty-Pagetable)。
    释放的 pipe 页面通过触发一个新的匿名映射被回收为末级页表。同一物理页面现在既是一张活跃的叶子页表,又是 pipe 仍在读写的数据页。向 pipe 写入八个字节即可植入一个伪造的 PTE;读取 pipe 即可读回该表。这是一种有限的任意物理读写,每张表大约有 460 个 PTE 窗口。

  3. 击败 KASLR。
    通过物理读取,我们扫描固定的低内存 SMP 跳板页表(KASLR 从不移动它);其内核半部分条目指向 level4_kernel_pgt(内核的物理基址)。从那里,init_top_pgt(可通过其自引用的条目 511 识别)是一个通用的虚拟到物理转换器,可以恢复内核虚拟基址,并将我们的地址空间与物理内存关联起来。

  4. 从有限读写到无限读写。
    我们在叶子表中伪造一个 PTE,使其指向该表自身的物理地址。对应的虚拟窗口随后别名化该页表本身,于是 PTE 变成了普通内存:无限制的任意内核读写,且循环中不再需要 pipe。通过执行一次超大的 mprotect() 强制进行完整的 mm 刷新,即可处理 Ring 3 的 TLB 一致性。

  5. 解析偏移量并获取凭据。
    结构体成员偏移量在运行时从 /sys/kernel/btf/vmlinux 中读取,而非硬编码。我们通过 vmemmap struct page 遍历和 mm_struct.owner 定位自己的 task_struct,将凭据 ID 清零,并在 credreal_cred 中填充所有能力集(capability sets)。符号地址来自内部解析器,该解析器通过我们的任意读取解析内核自身的 kallsyms 表;仅当失败时,我们才回退到将 cred.user_ns 指向 init_user_ns(这样 CAP_SYSLOG 在初始命名空间中有效),并从 /proc/kallsyms 读取真实地址。

  6. 在不翻转 enforcing 的情况下禁用 SELinux。
    我们覆盖 avc_denied() 的前导码,用一个 xor eax, eax ; ret 桩代码(在 IBT 下跳过 endbr64)。所有拒绝请求现在都返回 granted(允许),作用于整个进程,而 getenforce 仍报告 Enforcing。这也是逃逸的前提条件:核心转储处理器的跨域重新执行否则会被拒绝。

  7. 通过 core_pattern 逃逸。
    我们覆盖全局变量 core_pattern,添加一个以 | 为前缀的处理程序,通过 /proc/<pid>/root(崩溃任务的容器 chroot)指向我们自己的二进制文件,然后使子进程崩溃。内核以 usermodehelper 身份运行该处理程序,在初始命名空间中具有 root 权限,我们通过绑定在容器内部的 Unix 套接字传递一个交互式 root shell。处理程序诞生于初始命名空间,因此无需进行现场命名空间操作,也无需处理 PID 命名空间的那些风险。

相似文章

Dirtyfrag:通用 Linux 本地权限提升漏洞

Hacker News Top

一份名为“Dirty Frag”的报告详细描述了一种通用的 Linux 本地权限提升(LPE)漏洞。该漏洞通过串联两个内核错误,可在主要发行版上获取 root 访问权限。披露信息指出,由于保密期失效,目前尚无针对此关键安全问题的补丁。

CVE-2026-45257:通过kTLS-RX在FreeBSD中的本地权限提升

Lobsters Hottest

FreeBSD中存在一个严重的本地权限提升漏洞(CVE-2026-45257),允许无特权用户将任意数据写入任何可读文件的页面缓存,绕过文件权限和标志,最终导致完全获取root权限。该漏洞影响FreeBSD 13.0及更高版本的默认安装,通过sendfile、KTLS和内核内AES-GCM解密的不安全组合实现。

CopyFail: 从Pod到主机

Hacker News Top

Copy Fail 是一种新的 Linux 本地提权漏洞,它利用内核内存损坏缺陷重写页缓存,从而实现跨容器攻击和容器逃逸。