Linux内核堆强化漏洞利用研究
分析Linux内核的free列表指针混淆有一些缺陷,在适当的条件下,攻击者可以进行自由列表投毒攻击。
摘要
常见的堆利用技术中的空闲列表投毒会破坏堆分配器的空闲块的链接列表。堆分配后将返回投毒的地址,Linux内核引入了堆强化,这使这些链接列表中的指针会变得非常模糊。在不知道密钥和指针地址的情况下,攻击者无法可靠地用选定的地址毒化指针。在这篇文章中,我将分析Linux内核的free列表指针混淆有一些缺陷,在适当的条件下,攻击者可以进行自由列表投毒攻击。
漏洞介绍
Linux内核中的默认堆分配器是SLUB分配器。每个空闲块中都有一个指针,该指针是跟踪这些空闲块的链表的一部,空闲列表投毒是针对Linux内核的一项已知技术,在《内核开发指南:攻击核心》一书中有记录,2010年,攻击者使用精心设计的地址覆盖了空闲列表指针,该地址随后将在将来的堆分配中返回。
自2017年以来,使用配置选项CONFIG_SLAB_FREELIST_HARDENED在Linux内核中缓解了自由列表投毒的问题。
https://patchwork.kernel.org/patch/9864165/中显示了此缓解措施的补丁。
进行混淆的重要代码如下所示:
- static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,
- unsigned long ptr_addr)
- {
- #ifdef CONFIG_SLAB_FREELIST_HARDENED
- return (void *)((unsigned long)ptr ^ s->random ^ ptr_addr);
- #else
- return ptr;
- #endif
目标指针与指针的地址和一个随机值进行异或,每个主机的随机值是唯一的,我们可以看到,除非知道秘钥在块地址上也有信息泄漏,否则无法显示或覆盖此指针。
漏洞准备
理解攻击的关键是,指向空闲块的指针存储在类似的空闲块内。实际上,这意味着指针和这些指针的地址几乎相同,例如,分配2个16字节的内存块时,指针和指针的地址很可能仅在其较低的12位不同(对于具有12位页面大小的体系结构)。
当空闲列表指针被ptr ^ ptr_addr ^ s-> random混淆时,则由于ptr和ptr_addr共享相同的高位,这将导致ptr ^ ptr_addr的结果高位为0。因此,如果混淆指针的信息泄漏,那么我们随后可以泄漏s-> random的高52位。
还注意到,泄漏了s-> random的一些低位。SLUB分配器是基于board的分配器,它将分配舍入到board的大小。我们可以做出一些假设,即分配给我们的内存将与舍入后的board大小对齐。因此,如果我们分配16个字节的内存,则堆分配的低4位将为0。如果分配256个字节,则低8位将为0,如果分配4096个字节,则低12位将为零。但是,如果我们将board尺寸混合在一起,则对于不同的board会出现新的s-> random。
原创文章,作者: Admin ,转载请注明出处:https://secvery.com/3367.html