堆学习—fastbin二次释放

由于fastbin采用单链表结构(通过fd指针进行链接),且当chunk释放时,不会清空next_chunkprev_inuse,再加上一些检查机制上的不完善,使得fastbin比较脆弱。针对它的攻击方法包括二次释放,修改fd指针并申请(或释放)任意位置的chunk(或fake chunk)等,条件是存在堆溢出或者其他漏洞能够控制chunk的内容。

fastbin dup

一般而言,不同大小的free chuk会被分类到不同的bin中,而bin的类型可以被分为fast bin ,small bin,large bin 以及unsorted bin 。其中,fast bin的操作效率最高,为单向链表,其他的都是双向链表。较高的操作效率意味着较低的安全性(传统艺能—牺牲安全换效率),所以fastbin机制产生的漏洞也是堆区漏洞最重要的组成部分之一。

默认情况下,对于size_t为4B的平台, 小于64B的chunk分配请求;对于size_t为8B的平台,小于128B的chunk分配请求,程序会根据所需的size首先到fastbin中去寻找对应大小的bin中是否包含未被使用的chunk,如果有,则直接从bin中返回该chunk。而释放chunk时,也会根据chunk的size参数计算fastbin中对应的index,如果存在对应的大小,就将chunk直接插入对应的bin中。

32位平台 size_t 长度为 4 字节,64 位平台的 size_t 长度可能是 4 字节,也可能是 8 字节,64 位Linux平台 size_t 长度为 8 字节

而且为了追求效率,fastbin不仅使用单链表进行维护,由fastbin管理的chunk即使在被释放后chunk的p参数也不会被重置,而且在释放时只会对链表指针头部的chunk进行校验。

tcache dup

最后我们来看libc-2.26出现的tcache机制不会检查二次释放,因为tcache_put() 和 tcache_get() 分别用于从单链表中放入和取出 chunk。但是在做tache的这些机制的时候并没有进行有效性检查,因为tcache机制还在fastbin机制前面,于是很多以前fastbin做的有效性检查都失效了。

于是tcache dup机制更加简单了,直接释放两次就行,并且tcache机制同样是单链表操作,于是用于fastbin的fastbin dup into stack 攻击同样可以用于tcache dup into stack攻击。

fastbin dup consolidate

fastbin dup consolidate 是另一种绕过fastbin 二次释放检查的方法。我们知道libc在分配large chunk的时候,如果fastbin不为空 ,则调用malloc_conslidate ( )函数合并里面的chunk ,并放入UNsort bin ;接下来,unsort bin 中的chunk又被各自取回各自对应的bins。此时fastbins被清空,再次释放时也就不会触发二次释放。

需要注意的是,虽然fastbin chunk的 next chunk 的PREV_INUSE 标志永远为1,但是如果该fastbin chunk被放到了unsorted bin中,next chunk的PREV_INUSE也会被相应的修改为0.这一点对构造不安全的unlink攻击很有帮助。