18年。Linux 2.6.25,2007年12月,commit 42e30bf3463c。那个时候 iPhone 刚发布半年,Android 还没面世,内核社区往 SCTP 的 ASCONF 实现里加了一段 wildcard 处理逻辑。谁也没想到这段代码会在 2026 年被一台 AI 驱动的漏洞挖掘管线揪出来——CVE-2026-64564,CVSS 4.0 评分 8.5,本地提权 + 容器逃逸,影响从 5.14 到 7.2-rc2 的主流内核。

发现方是腾讯朱雀实验室的 Corvus AI——一套持久化的多智能体内核漏洞研究管线。以下基于他们的完整技术报告,拆解漏洞原理、利用链和修复逻辑。

SCTP 与 ASCONF 背景

SCTP(Stream Control Transmission Protocol)是 RFC 4960 定义的消息导向传输协议,跟 TCP/UDP 最大的区别是多宿主(multihoming)——一个 association 可以绑定多个 IP 路径。内核用 struct sctp_association 表示 association,用 struct sctp_transport 表示每条路径,transport 挂在 asoc->peer.transport_addr_list 链表上。另外有两个关键缓存指针:

peer.primary_path ───→ transport A
peer.active_path  ───→ transport A

这两个指针预期始终指向 association 拥有的活跃 transport。

RFC 5061 给 SCTP 加了动态地址重配置(ASCONF),允许运行时增删路径、切换主路径。ASCONF chunk 结构是:一个 Address Parameter + 若干操作参数(ADD-IP、DEL-IP、SET-PRIMARY 等),按消息顺序处理。

问题就出在这个顺序处理上。

身份不匹配:一个 DEL-IP 用了两个不同的"我是谁"

触发条件很精妙。攻击者构造一个 ASCONF chunk:

[ Address Parameter = L ]   ← 用来查找 transport
[ DEL-IP L            ]   ← 验证删除权限时看的是 IPv4 包源地址 S
[ DEL-IP 0.0.0.0      ]   ← wildcard,保留当前 transport 指针

如果你让 IPv4 包源地址 S ≠ Address Parameter L,DEL-IP L 的权限检查会通过(内核用 S 验证"你有权删除这条路径"),于是 transport(L) 被从 association 中移除并释放。随后 wildcard DEL-IP 把刚释放的 transport 指针保留为 "操作对象"。

结果:peer.primary_pathpeer.active_path 指向一个已经 RCU 释放的 sctp_transport。后续任何通过这两个指针访问的 socket 操作(比如 getsockopt(SCTP_STATUS))都会触发 use-after-free。

上游修复只有三行:

peer = sctp_assoc_lookup_paddr(asoc, &addr);
if (!peer) return SCTP_ERROR_DNS_FAILED;
+ if (peer == asconf->transport)
+     return SCTP_ERROR_REQ_REFUSED;
sctp_assoc_rm_peer(asoc, peer);

拒绝删除 ASCONF chunk 自己选中的 transport。简单到让人想问"这难道不是一开始就该写的?"

利用链:六步从用户态到 root

Corvus AI 构造了一条完整的利用链,不需要 ROP,不需要 shellcode,纯数据导向。

第一步:稳定触发 UAF。 不是随便删一个 transport 就能用。如果删的是 ACTIVE primary,association 的定时器和引用计数会阻止 transport 真正释放。如果删的是 UNCONFIRMED secondary,transport 是释放了,但后续协议处理会销毁整个 association。甜点区是:一个 confirmed ACTIVE secondary——先通过 heartbeat 把它升到 ACTIVE,关掉所有路径的 heartbeat,再注入恶意 ASCONF。稳定触发后,把 ASCONF 包的源地址黑洞掉,防止 ASCONF-ACK 分配新 transport 抢占释放的 slot。

第二步:pg_vec 泄漏内核地址。 sctp_transport 占 kmalloc-1024。用 TPACKET V1 发送环(128 block)分配一个 1024 字节的 pg_vec 数组,让它回收 UAF transport 的内存槽。此时 getsockopt(SCTP_STATUS) 把 pg_vec 里的页指针当成 transport 字段解读,srttcwnd 字段恰好拼出一个 64 位内核 direct-map 地址。同一个物理页在用户态有映射,在内核态也有地址——后续所有伪造对象都放在这个页里,通过泄漏的 direct-map 地址引用。

第三步:4 字节任意内核读。 SCTP_STATUS 返回的 assoc_id 来自 sctp_assoc2id(transport->asoc)。控制 transport->asoc 指向目标地址减去 offsetof(sctp_association, assoc_id),就能读出目标地址的 4 字节。

第四步:绕过 KASLR。 通过第三步读 CPU entry area 里 IDT 的 gate 0,重建 asm_exc_divide_error 的运行时地址,算出 KASLR slide。UMIP 阻止用户态 sidt,但内核读不受影响。

第五步:commit_creds()。 第二个 vulnerable association 用于安装完全受控的 transport 对象。msg_msg 分配走 kmalloc-cg-1024(GFP_KERNEL_ACCOUNT),SCTP transport 走 kmalloc-1024,不冲突。持久化的 SCTP authentication-key 分配在正确的 slab 里放入受控数据。构造的假对象图:

stale active_path│▼
[ reclaimed transport / embedded packet ]├── packet->transport ──────→ [ fake transport ]├── asoc ────────────────────→ [ fake association ]│                                   ├── base.sk ──→ [ fake socket / cred ]│                                   └── af_specific → [ fake ops ]│                                           ├── get_dst → 正常函数│                                           └── get_saddr → commit_creds└── dst ──────────────────────→ NULL

触发路径:setsockopt(SO_LINGER) → close() → SCTP ABORT 生成 → 输出队列刷新 → sctp_transport_route() → af_specific->get_saddr(fake_sk) → commit_creds(controlled_cred)

第六步验证:读 /etc/shadow、在 /root 下创建文件,确认全局 root。

容器逃逸:6/8 成功率,不需要特权

之前 PoC 需要 net.sctp.addip_enablenet.sctp.addip_noauth_enable 两个 sysctl,看似需要 CAP_NET_ADMIN。Corvus AI 后来发现 SCTP_ASCONF_SUPPORTEDSCTP_AUTH_SUPPORTED 可以在 socket 级别启用,带合法 AUTH chunk 的触发包就能工作。容器不需要 CAP_NET_ADMIN、不需要 CAP_SYS_ADMIN,默认 seccomp 策略下就能跑。

容器逃逸的最后一步:commit_creds 回调替换为 call_usermodehelper_exec(),在初始命名空间里执行宿主机 root 操作。实测 8 次成功 6 次,失败的两次停在指针遍历不命中,没 panic。

修复和时间线

时间 事件
2007-12 / 2.6.25 引入漏洞的 wildcard 逻辑合入
2026-07-12 Corvus AI 从软锁死推进到 post-RCU crash
2026-07-12 私密披露,附带 PoC 和补丁
2026-07-15 首个稳定的全局 root 利用链完成
2026-07-15–23 在 5.14/6.6/6.8/6.12 目标上验证
2026-07-24 修复进入 Linux networking tree
2026-07-27 容器逃逸验证通过
2026-08-04 CVE-2026-64564 公告

修复已在 6.6.148、6.12.101、6.18.42、7.1.6 等稳定分支落地。主线 commit 9b2854f86f0b

一个内核开发者的视角

这个漏洞让我想了几个问题。

第一,SCTP 本身的使用面有多广? 说实在的,大部分 Linux 服务器不会主动用 SCTP,但内核默认编译了 sctp.ko,容器环境里 modprobe 就可能加载。如果你跑的是容器平台(K8s node 上有 tenant 容器),攻击者不需要你"用"SCTP——他只需要能加载模块。

第二,18 年的漏洞说明什么? 不是什么"内核代码质量差"——SCTP 的 ASCONF 实现其实写得挺规矩。问题在于协议状态机的边界条件复杂到人类审码很难穷举,而这次是 AI 驱动的多智能体管线把边界条件探索变成可重复的工程流程。Corvus AI 不是找了一个 bug,是建了一条流水线。

第三,利用链的设计值得学。 没有 ROP、没有 shellcode,全凭数据导向——用 pg_vec 回收、direct-map 泄漏、IDT 读 KASLR、authentication-key 写受控对象。每一步都有验证和回退。这条链的工程化程度不亚于漏洞本身。

如果你维护内核或容器平台:检查 net.sctp.addip_enable 和相关 sysctl,升级到对应稳定分支。如果你是做漏洞研究:Corvus AI 的公开报告本身就是一份很好的方法论参考。

⚠️ 网络安全免责声明

本文内容仅供技术研究与安全学习之用。文中描述的漏洞分析、攻击链拆解和代码示例均基于公开披露的安全研究,旨在帮助开发者理解攻击原理、提升安全意识和防御能力。

请勿将本文所述技术用于任何未经授权的安全测试、渗透攻击或非法用途。任何因滥用本文信息而造成的法律后果,由使用者自行承担,与本文作者无关。

如发现系统安全漏洞,请通过合法渠道向相关厂商或平台报告,共同维护网络安全生态。


参考:Tencent Zhuque Lab — SCTPhantom: An 18-Year-Old SCTP ASCONF Transport Use-After-Free

返回列表