House of Corrosion, 无需泄露任何的地址即可getshell,适用于glibc2.27,利用条件是存在一个可以写至少10字节的UAF漏洞,存在1/16的爆破。首先释放一个NO_MAIN_ARENA被置为1的largebin,利用unsorted bin attack覆写global_max_fast,此时unsorted bin bk指针被覆写为了dumpe_main_arena_end的地址,在此地址上伪造一个large bin,size大小与释放的largebin相同。利用fatbin 的特性即文中提到的原语1,2,3覆写stderr结构体的成员变量和vtable指针,覆写_s._allocate_buffer函数指针为call eax的gadget,_IO_buf_end,_IO_buf_base之间的差值为one_gadget的地址。之后申请一个chunk触发unsorted bin的清空,伪造的chunk就会被插入到largebin链表中,在插入过程中触发NO_MAIN_ARENA的检查断言,进而刷新stderr,调用改写之后的vtable,进入IO_str_overflow,调用_s._allocate_buffer函数指针,也就是call eax,此时eax是_IO_buf_base,_IO_buf_end之间的差值, 也就是one_gadget, getshell。
House Of Corrosion
是是一种针对glibc 2.27\\\\2.29
的堆利用技术,可以在不泄露地址的情况下完成getshell
。其主要的原理是覆写global_max_fast
,从而将堆地址写入fastbin[i]
指定的位置。
利用的前提条件是存在一个UAF
漏洞,可以造成WAF 10 bytes
。并且需要随机爆破4 bits
的地址(1/16
的概率)。其利用流程如下
UAF
构造unsorted bin attack
爆破,覆写global_max_fast
UAF
和fastbin attack
覆写stderr
stderr
,getshell
利用unsorted bin attack
将global_max_fast
覆写为main_arena
附近的地址之后,再次释放堆块就会进入fastbin[i]
中,也就是将释放堆块的地址写入fastbin[i]
的位置,其中目标地址与申请的堆块大小之间的关系是
chunk_size = (delta * 2) + 0x20
其中delta
是第一个fastbin
与目标地址之间的距离(以字节为单位)。需要注意的是在free
的时候会存在一个检查
if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)");
这里这个old
是目标地址中存储的值。根据free
的调用流程,发现__libc_free
在调用_int_free
函数时将have_lock
置为了0
,因此这里就不会存在这个检查,相关代码如下
void
__libc_free (void *mem)
{
//...
_int_free (ar_ptr, p, 0);
}
static void
_int_free (mstate av, mchunkptr p, int have_lock){
//...
}
此时我们可以将target address
覆写为一个堆地址,该堆块属于fastbin
。
在原语1
中我们已经将target address
覆写为了堆地址,那么此时只要我们利用UAF
覆写堆块的fd
指针为value
,在将该堆块申请回来,根据fastbin
的特性,target address
中的内容就会被改写为value
。如下所示
target->heap_address->NULL;
//UAF overwrite fd
target->heap_address->value;
//malloc heap
target->value;