Freebsd UMA内核堆安全特性解读
2021-1-11 17:52:44 Author: mp.weixin.qq.com(查看原文) 阅读量:0 收藏

1.1 简介

Freebsd的内核内存分配器叫做UMA(Universal Memory Allocator),这篇文章只关心它的安全特性,对于常规功能实现请读者朋友参考网络上的其他文章。它的安全功能特性相比XNUNTLINUX都少了很多,并且还存在一些不安全的构架设计,下面将会详细分析。

1.2 架构设计缺点

UMA的总体架构也是基于solaris slab, 我们直接看最底层的slab结构,一个slab大小为PAGE_SIZEslab的管理体结构依据slab里的每个item大小而决定,对于小块itemslab管理结构体放在slab里,并且是放到PAGE_SIZE的最后。对于大块item,管理结构体则单独分配一个内存,不包含在slab里。

       <---------------Page (UMA_SLAB_SIZE) ---------->

       __________________________________________

      | _  _  _  _  _  _  _  _  _  _  _  _  _  _  _   ___________ |

      ||i||i||i||i||i||i||i||i||i||i||i||i| |slab header||

      ||_||_||_||_||_||_||_||_||_||_||_||_||_||_||

      |_________________________________________|

       This is an OFFPAGE slab. These can be larger than UMA_SLAB_SIZE.

       ______________________________________

      | _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _   |

      ||i||i||i||i||i||i||i||i||i||i||i||i||i||i||i|  |

      ||_||_||_||_||_||_||_||_||_||_||_||_||_||

      |_____________________________________-|

        ___________    ^

       |slab header|   |

       |___________|---*

对于小块itemslab这种设计属于严重的安全错误设计,slab header放在所有item的最后,如果最后一个item发生溢出,就可以直接覆盖slab header里的数据结构。

struct uma_slab {        uma_keg_t       us_keg;                 /* Keg we live in */...}

Slab header结构为struct Uma_slab,它的第一个成员是us_keg

struct uma_keg { LIST_HEAD(,uma_zone)    uk_zones;       /* Keg's zones */...}

Uk_zones结构为:

struct uma_zone {        uma_ctor        uz_ctor;        /* Constructor for each allocation */        uma_dtor        uz_dtor;}

结构体成员uz_ctoruz_dtor为每个zone在创建和销毁时调用的析构函数指针,exploit程序一般都会替换这两个函数指针,使其指向shellcode地址。Slab header放在最后,使堆溢出攻击相对linux变得更加简单, 因为linuxslab header就是放在最前面的。我们在设计内存分配器时就要避免这个糟糕的设计,同时管理结构体中函数指针的定义一定要做到最少,防止被exploit程序滥用。

1.3 安全特性缺失

1.3.1 溢出检测

能检测到溢出情况的发生是每个内存分配器的基础安全能力,业界的通用算法是在内存区块的前后加入redzone,在初始化时填充一个固定值,在内存释放时检测redzone里的固定值是否有改变来判断是否有溢出行为的发生。

UMAredzone结构为:

-----------------------------------------------------------------------------

| struct stack | size |0x42|0x42|...|    data       |0x42|0x42|...|

-----------------------------------------------------------------------------

data的前面分别为struct stack 保存的是当前栈信息,sizedata的大小,0x42则为redzone的固定值,一共16字节。在data的最后同样为16字节的固定值。

由于设置redzone会占用更多的内存,同时会使初始化和释放逻辑变得复杂,从而影响效率,所以检测溢出的发生都是作为debug选项来开启的。几乎所有主流的os内核内存分配器在设置redzone时都使用了固定值,笔者认为这也是一个不安全的设计,exploit编写者可以精心构造内存结构,使其shellcode地址指向0x42424242,就可以绕过检测。

1.3.2 UAF检测

对于UAF(Use After Free)的检测,freebsd没有实现这个功能,一般算法是在slab item释放时对data区域填充固定的值,在分配时先检测固定值有没有被污染,以此来判断有无UAF的发生。

1.3.3 双向安全链表

双向链表的删除操作时,要先检测前后节点是否为合法地址, freebsd同样没有设计这个功能。

1.3.4 item地址随机化

Slab里保存的item为了初始化简单, 每个item都是顺序链接的, 这给exploit程序的利用提供了极大的方便。Linux内核使用了洗牌算法将item的链接顺序打乱来规避这种攻击。Freebsd没有提供这个功能。

1.3.5 管理结构体cookie

同样为了检测是否有内存破坏的现象, 通常会在一些管理结构体中加入一个随机化的cookie值,内存释放时判断cookie是否有被污染。freebsd没有提供这个功能。


文章来源: https://mp.weixin.qq.com/s?__biz=Mzg4NjU1NDU4MA==&mid=2247483710&idx=1&sn=b91c0b55bb96ad5f3690ab64fca43780&chksm=cf96ab85f8e1229361adbac5051bf63a950f6c0f06e7fd8d384ec636390fabf41985adf7e504&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh