一个存在了37年的内核漏洞,最近被人翻了出来,还配上了能直接拿root权限的利用代码。
![]()
安全研究团队Calif公布了一份概念验证(PoC)利用程序,通过串联两个内核缺陷,在OpenBSD系统上实现本地提权。主漏洞可以追溯到约37年前的原始BSD源代码。OpenBSD在Calif于2026年10月16日发布利用代码之前,已经修复了这两个问题。公布的研究内容只涉及本地权限提升,没有报告该漏洞在真实攻击中被使用。
这个数字本身就很扎眼:37年。一段代码从BSD时代一路活到今天,中间经历了无数次审计、重构、加固,愣是没人发现。
第一个漏洞:一个16位计数器撑不住了
问题出在System V共享内存的处理上。一个名为shm_nattch的共享内存附加计数器,用的是有符号16位数值。本地用户只要反复fork带共享内存记录的进程,就能把这个计数器推过它的最大值32767。
数字一旦越界,就会回绕成负值。这个整数溢出会引发竞态条件,最终导致内核中的释放后使用(use-after-free)。第二个漏洞则提供了一个有条件的越界写,让研究者有足够的控制力,把内存破坏转化成root权限。
怎么把内存破坏变成root
Calif的利用程序做了这么几件事:映射127个共享内存段,移除它们的映射,然后fork出259个进程,逼计数器回绕。接着塑造内核堆内存,通过sysctl(KERN_MALLOCSTATS)观察分配器数据。
一个进程用IPC_RMID标记某个共享内存对象待删除,另一个辅助进程则在合适的时机尝试附加新段。赢下这场竞态,就能造出一个大小错配的内核分配。
接下来,研究者把IP套接字对象放在被释放内存附近,用IP_MULTICAST_TTL创建一个持久的struct ip_moptions对象。越界写会改动这个结构里的两个成员计数器。
关闭套接字会启动原子计数器变更,进而改变OpenBSD的自引用页表映射。这让用户空间的映射对超级用户模式可见,利用程序就能覆写一个可预测的内核指针。
最后,利用程序在内核中执行代码,修复被改动的指针,打开一个root shell。
开着防护也能打穿
这条利用链在KARL、SMAP和SMEP等OpenBSD防护开启的情况下依然奏效,而且不需要单独的信息泄露。KARL会在启动时改变内核代码和数据的地址。但Calif发现,在同一硬件上,内核内存分配器的部分区域仍然可预测。早期启动对象会落在稳定位置,让利用程序可以瞄准lo0和enc0的ioctl处理函数指针。
OpenBSD在Errata 018中修复了整数溢出,在Errata 026中修复了引用计数导致的释放后使用。OpenBSD 7.9的errata页面列出了针对所有架构的这两个修复。amd64、i386和arm64系统可以通过syspatch获取二进制更新。管理员应当应用所有可用补丁并重启,让修正后的内核生效。
Calif还提出了更广泛的防护建议,包括对链表做安全的unlink检查、页表映射随机放置、降低内核分配的可预测性。数组边界检查和分配隔离这类编译器特性,也能让类似的内存缺陷更难被利用。
PoC源代码已经公开。Calif的代码仓库把这项工作标注为其MAD Bugs安全研究项目的一部分。
这件事说明,老旧的设计选择可以在受信任的操作系统代码里潜伏几十年。就在不久前,还有一起27年历史的OpenBSD认证漏洞,以及更早的OpenBSD NFS双重释放漏洞被翻出来。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.