内核堆加固机制的脆弱性分析

来自于原文"Weaknesses in Linux Kernel Heap Hardening"。

总结:free_list poisoning是堆漏洞利用的常用方法,原理是将fd指针改成指向目标地址,这样下一次分配就会将分配到我们的目标地址。然而linux内核引入了堆加固机制,会将fd指针异或加密,导致利用受阻。本文分析一下这种加固机制的脆弱性,在特定情况下,攻击者还是能够利用free_list poisoning

1. 介绍内核堆加固机制

在2017年开始,内核开始引入内核堆加固机制。编译选项是CONFIG_SLAB_FREELIST_HARDENED,patch见https://patchwork.kernel.org/patch/9864165/。

*
* Returns freelist pointer (ptr). With hardening, this is obfuscated
* with an XOR of the address where the pointer is held and a per-cache
* random number.
*/
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 

目标指针与某个地址指针和一个随机值异或加密,这个随机值对于每个slab都不一样,slab知识可以看看SLAB分配器概述

2.利用面分析

首先需要明白,指向空闲块的指针和被存放在类似大小的空闲块中。也就是说,堆指针和指针所在地址的值相似,例如,分配2个16字节的堆块,很有可能指针和指针所在的地址只有低12bit不同(页大小为4K)。

当free_list 指针被混淆为ptr ^ ptr_addr ^ s->randomptrptr_addr的高位是相同的,导致高位异或ptr ^ ptr_addr的结果是0。也就是说如果有信息泄露漏洞,我们可以泄露s->random的前52 bit。

同时注意,我们泄露了几个s->random的低比特。可以预测,slab块是对齐的,如果分配16字节堆块,则低4bit为0 ;如果分配256字节堆块,则低8bit为0 ;如果分配字4096堆块,则低12bit为0 。所以分配不同大小的slab,我们能够泄露s->random中不同的比特位。

3.利用

如果要实施free_list poisoning,首先我们需要一个信息泄露。假设已经申请了1个16字节的堆块,我们需要知道该空闲块内存中的free_list pointer值(64位系统,则为前8字节,类似于FD)。泄露出free_list pointer值之后,前52bit和后4bit就是secret值(s->random)。

现在进行free list pointer corruption,先分配16字节堆块再释放,目标是修改FD为目标地址TARGET_PTR。空闲块的地址记为PTR_ADDR

secret = high_bits_of_secret | low_bits_of_secret;

OBFUSCATED_POINTER = TARGET_PTR ^ secret ^ PTR_ADDR;

问题:目前我们只知道56bit的secret值,还有8bit未知。虽然这8bit未知,但有一定几率返回同一内存页的地址,只要能控制整个内存页(即所有返回值指向的内存),就有可能利用成功。

4.结论

作者提交了1个patch解决这个问题。

kmalloc-32 freelist walk, before:

ptr              ptr_addr            stored value      secret
ffff90c22e019020@ffff90c22e019000 is 86528eb656b3b5bd (86528eb656b3b59d)
ffff90c22e019040@ffff90c22e019020 is 86528eb656b3b5fd (86528eb656b3b59d)
ffff90c22e019060@ffff90c22e019040 is 86528eb656b3b5bd (86528eb656b3b59d)
ffff90c22e019080@ffff90c22e019060 is 86528eb656b3b57d (86528eb656b3b59d)
ffff90c22e0190a0@ffff90c22e019080 is 86528eb656b3b5bd (86528eb656b3b59d)
...

after:

ptr              ptr_addr            stored value      secret
ffff9eed6e019020@ffff9eed6e019000 is 793d1135d52cda42 (86528eb656b3b59d)
ffff9eed6e019040@ffff9eed6e019020 is 593d1135d52cda22 (86528eb656b3b59d)
ffff9eed6e019060@ffff9eed6e019040 is 393d1135d52cda02 (86528eb656b3b59d)
ffff9eed6e019080@ffff9eed6e019060 is 193d1135d52cdae2 (86528eb656b3b59d)
ffff9eed6e0190a0@ffff9eed6e019080 is f93d1135d52cdac2 (86528eb656b3b59d)

参考:

Weaknesses in Linux Kernel Heap Hardening

Linux slub 分配器上的安全加固学习

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值