ipv6_frag_escape: Linux 本地提权 - 可靠的容器/沙盒逃逸
摘要
针对 Linux 本地提权和容器/沙盒逃逸的概念验证,利用内核中的 IPv6 分片漏洞,目标是 CentOS/RHEL 10。
查看缓存全文
缓存时间: 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 10 | 6.12.0-242.el10 | root,容器逃逸 |
| RHEL 10 | 6.12.0-228.el10 | httpd_t 上下文逃逸 |
利用链
-
从 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 进行时序配合,这也是该技术容错性高的主要原因。 -
从页面 UAF 到脏页表(Dirty-Pagetable)。
释放的 pipe 页面通过触发一个新的匿名映射被回收为末级页表。同一物理页面现在既是一张活跃的叶子页表,又是 pipe 仍在读写的数据页。向 pipe 写入八个字节即可植入一个伪造的 PTE;读取 pipe 即可读回该表。这是一种有限的任意物理读写,每张表大约有 460 个 PTE 窗口。 -
击败 KASLR。
通过物理读取,我们扫描固定的低内存 SMP 跳板页表(KASLR 从不移动它);其内核半部分条目指向level4_kernel_pgt(内核的物理基址)。从那里,init_top_pgt(可通过其自引用的条目 511 识别)是一个通用的虚拟到物理转换器,可以恢复内核虚拟基址,并将我们的地址空间与物理内存关联起来。 -
从有限读写到无限读写。
我们在叶子表中伪造一个 PTE,使其指向该表自身的物理地址。对应的虚拟窗口随后别名化该页表本身,于是 PTE 变成了普通内存:无限制的任意内核读写,且循环中不再需要 pipe。通过执行一次超大的mprotect()强制进行完整的 mm 刷新,即可处理 Ring 3 的 TLB 一致性。 -
解析偏移量并获取凭据。
结构体成员偏移量在运行时从/sys/kernel/btf/vmlinux中读取,而非硬编码。我们通过 vmemmapstruct page遍历和mm_struct.owner定位自己的task_struct,将凭据 ID 清零,并在cred和real_cred中填充所有能力集(capability sets)。符号地址来自内部解析器,该解析器通过我们的任意读取解析内核自身的kallsyms表;仅当失败时,我们才回退到将cred.user_ns指向init_user_ns(这样CAP_SYSLOG在初始命名空间中有效),并从/proc/kallsyms读取真实地址。 -
在不翻转 enforcing 的情况下禁用 SELinux。
我们覆盖avc_denied()的前导码,用一个xor eax, eax ; ret桩代码(在 IBT 下跳过endbr64)。所有拒绝请求现在都返回 granted(允许),作用于整个进程,而getenforce仍报告Enforcing。这也是逃逸的前提条件:核心转储处理器的跨域重新执行否则会被拒绝。 -
通过 core_pattern 逃逸。
我们覆盖全局变量core_pattern,添加一个以|为前缀的处理程序,通过/proc/<pid>/root(崩溃任务的容器 chroot)指向我们自己的二进制文件,然后使子进程崩溃。内核以 usermodehelper 身份运行该处理程序,在初始命名空间中具有 root 权限,我们通过绑定在容器内部的 Unix 套接字传递一个交互式 root shell。处理程序诞生于初始命名空间,因此无需进行现场命名空间操作,也无需处理 PID 命名空间的那些风险。
相似文章
Dirtyfrag:通用 Linux 本地权限提升漏洞
一份名为“Dirty Frag”的报告详细描述了一种通用的 Linux 本地权限提升(LPE)漏洞。该漏洞通过串联两个内核错误,可在主要发行版上获取 root 访问权限。披露信息指出,由于保密期失效,目前尚无针对此关键安全问题的补丁。
Fragnesia:新的Linux权限提升漏洞利用
一个名为Fragnesia的新的Linux权限提升漏洞利用已在GitHub上发布,并附有概念验证代码。
Linux漏洞、禁运失效与补丁窗口缩短
一份关于2026年5月发现的三个严重Linux本地权限提升漏洞的报告,强调了披露模型的崩溃及其对生产环境的影响。
CVE-2026-45257:通过kTLS-RX在FreeBSD中的本地权限提升
FreeBSD中存在一个严重的本地权限提升漏洞(CVE-2026-45257),允许无特权用户将任意数据写入任何可读文件的页面缓存,绕过文件权限和标志,最终导致完全获取root权限。该漏洞影响FreeBSD 13.0及更高版本的默认安装,通过sendfile、KTLS和内核内AES-GCM解密的不安全组合实现。
CopyFail: 从Pod到主机
Copy Fail 是一种新的 Linux 本地提权漏洞,它利用内核内存损坏缺陷重写页缓存,从而实现跨容器攻击和容器逃逸。