AI News HubLIVE
站内改写3 分钟阅读

当AI让0-day漏洞感觉像N-day漏洞

本文深入分析了作者如何借助AI发现并利用Linux内核net/sched子系统中的一个释放后使用(UAF)漏洞,实现本地权限提升(LPE)。详细介绍了竞争条件的发现、优化过程,以及各种利用技术,并展示了利用AI加速漏洞开发各个环节的经验。

来源Hacker News AI作者: BeatrizPerez

当AI让0-day漏洞感觉像N-day漏洞

引言

在对net/tls漏洞进行n-day分析并为已修补的net/rxrpc漏洞编写exp之后,作者转向了0-day漏洞挖掘。在AI的帮助下,他在net/sched中发现了一个释放后使用(UAF)漏洞,并据此创建了一个本地权限提升(LPE)exploit。本文深入介绍了该exploit的技术细节,以及如何针对TyphoonPwn 2026中的CentOS 9桌面进行优化。此外,还简要展示了在kernel/events/core.c中发现的另外两个可利用漏洞(其中一个已有LPE exploit)。

AI的使用

与之前为net/rxrpc的n-day编写exp相比,作者更注重快速完成和改进这个exploit,而不是从头全面理解每个方面。因此,他使用AI来加速各个阶段:发现漏洞、生成KASAN PoC以及改进竞争条件。AI在快速迭代方面确实很有帮助,但推理能力仍然不足,且有明显的盲点。在微调时,作者仍然需要运用自己的判断力。

net/sched的简要概念

net/sched是Linux中的包调度子系统,位于设备驱动之上,决定何时、以何种顺序以及是否传输数据包。它还通过netlink提供API来配置包处理规则。每个网络设备都附加一个Qdisc(队列规则),其中包含所有配置数据。为了决定如何处理给定数据包,net/sched引入了链、过滤器和动作。链是过滤器的有序列表,过滤器检查数据包中的特定属性,然后根据结果决定执行什么动作。net/sched的设计允许最大程度地重用组件——多个网络设备可以共享同一个Qdisc。关键的是,动作可以在同一网络命名空间内共享,并通过“索引”唯一标识。一个per-net的radix树action_idr记录所有动作对象,并支持通过索引查找,这由tcf_idr_check_alloc函数实现。

漏洞

该漏洞是一个锁不匹配问题:tcf_idr_check_alloc()仅持有rcu_read_lock()就访问动作idr,而动作释放时持有idrinfo->lock和rtnl_lock(),但没有等待RCU宽限期(即直接kfree)。这导致了一个竞争条件:动作可以在查找过程中被释放,从而产生UAF场景。成功利用UAF需要在同一窗口内既释放又回收动作(覆盖tcfa_refcnt)。竞争的基本结构是:CPU0查找动作,CPU1删除动作,CPU2回收并设置tcfa_refcnt为非零。

作者最初使用RTM_NEWACTION和RTM_DELACTION证明了漏洞,但这些操作需要init命名空间中的CAP_NET_ADMIN,因此不可行。于是转而使用RTM_NEWTFILTER和RTM_DELTFILTER。通过使用clsact qdisc和flower过滤器(设置了DOIT_UNLOCKED标志),可以避免持有rtnl_lock。此外,利用还需要非特权用户命名空间启用。

竞争优化

第一个优化是使用timerfd和epoll的窗口扩大技术。通过设置timerfd,在特定时间后触发硬件中断,处理程序会唤醒所有等待者。附加大量epoll对象可以延长等待者列表,从而阻塞CPU。第二个优化是让不同线程在不同的链上创建过滤器,每个链有自己的互斥锁,使用独立链可以显著加速竞争。第三个优化是主要重构:利用错误路径消除大量开销。设置两种竞争线程:binder(绑定器)和deleter(删除器)。

Binder线程利用过滤器创建的错误路径:提交一个包含两个动作的过滤器创建请求——动作42和一个无效格式动作。动作42被成功获取(竞争发生于此),但读取第二个动作失败导致中止,过滤器从未创建,动作42也未被插入idr。这节省了删除新创建过滤器的开销。Deleter线程创建一个包含动作42的过滤器然后删除它,其作用是将动作42插入idr。最终设置:N个binder线程和一个deleter线程在不同CPU上运行,全部操作动作42。利用时间从超过15分钟缩短到约5秒。

kASLR泄露

利用开始时,作者使用EntryBleed实现泄露kASLR基址。

利用原语

tc_action对象丰富,在回收后的代码路径中存在许多有用原语,例如任意kfree user_cookie->data和user_cookie。本exploit使用了ops虚表中的间接调用。tc_action从kmalloc-256高速缓存分配,作者用user_key_payload对象回收。为了避免崩溃,将数据的前8个字节设置为指向NULL的指针(通过kASLR泄露获得)。更优的方法是将数据长度设为192字节,使临时缓冲区落入不同的kmem_cache。

RCU

在获得RIP控制之前,需要简要了解Linux RCU机制。RCU是一种低成本同步机制,所有读取在“宽限期”内完成,写入在之后。通过call_rcu(head, func)函数延迟写入,它接受rcu_head指针和函数指针,将回调添加到每CPU链表中,在宽限期后调用。RCU的rcu_head结构包含next指针和func函数指针。利用时,通过控制user_key_payload中的rcu_head结构,可以劫持控制流。