Pspray: Timing Side-Channel based Linux Kernel Heap Exploitation Technique

虽然研究方向目前不是这个,但上个学期因为课程缘故,精读完这篇顶会论文以后,不禁赞叹,韩国那边的作者团队真的太细致了,对这一时序侧信道问题进行了如此精细的思考和测试,还提出了缓解方案,甚至基于未来应用该方案的考量,对其进行了性能测试。无论是不是做相关领域的事情,都要有这种探究精神👍很棒很棒

但在反复思考的过程中,发现了缓解方案仍然可以被绕过💀,当时放在课程报告里面了,刚刚想起来,感觉还是搬出来吧

不清楚这篇文章说的什么也没关系,是作者团队发现的一个能提升内核pwn成功率的时序侧信道利用方法,以下附带课程报告里的本文简介

原文请移步https://www.usenix.org/conference/usenixsecurity23/presentation/lee-yoochan

本文简介

Linux v4.8及以上内核提供CONFIG_SLAB_FREELIST_RANDOM配置选项,开启后会让SLUB分配器在内核创建新的slab时对空闲列表的顺序进行根据上下文的伪随机化

因为这个机制的存在,不清楚slab内部分配顺序和状况的攻击者,很难精确地将存在对象漏洞的对象块与目标对象块放到漏洞利用成功条件所需要的相对位置。这就导致容易造成内核崩溃。

SLUB分配器的分级对象分配机制来加速性能,其使用五种不同的路径(即快速路径、中等路径#1、#2、#3和慢速路径)来分配对象。如下图:

  PSPRAY方法的核心思想在于,如果SLUB的分配路径有快慢之分,而且进入慢路径意味着Buddy分配器产生了一个新slab的话;换言之,我们能从时序这一侧信道推断内存分配情况,通过这一信息,合理调整对象喷射策略,便能大大提升漏洞利用的成功率。

针对内核态下的三种内存破坏漏洞,越界(Out-Of-Bounds, OOB),释放后重用(Use After Free, UAF),双重释放(Double Free)利用PSPRAY:

如步骤b所述,对于对象越界(OOB)的漏洞,可以不断进行单个对象分配的请求,并且记录每步对象分配下,内核完成对象内存分配的时间,时间开销较大时即可推断内核刚刚进入了慢路径,即处于Buddy分配器分配了一个新slab,并且刚刚已分配一个对象的状态。

如步骤c所述,此时精确地控制对象申请的次数,直至恰好申请完整个slab。

如步骤d所述,之后继续精确地控制目标对象(T)喷射的次数,直至恰好剩余最后一个对象才能填满slab。

如步骤e所述,紧接着,攻击者分配包含OOB漏洞的块时,其会申请到这最后一个空闲的对象,这时候就很容易让存在对象越界漏洞的对象,能够按越界漏洞利用的要求,分配到目标对象的前一个位置。

当然,仍存在1种漏洞利用失败的可能性:剩下最后一个位置是整个slab最高地址的位置,如图所示。

所以PSPRAY的OOB成功概率取决于slab的N个位置里,分配最后一个对象的位置:

对于对象释放后重用(Use After Free, UAF)和双重释放(Double Free)的漏洞,其实漏洞利用成功对对象分配位置的要求,是类似的,即被释放对象与目标对象被分配到同一个位置。

如步骤b所述,对于UAF&DF的漏洞,也可以不断进行单个对象分配的请求,并且记录每步对象分配下,内核完成对象内存分配的时间,时间开销较大时即可推断内核刚刚进入了慢路径,即处于Buddy分配器分配了一个新slab,并且刚刚已分配一个对象的状态。

如步骤c~e所述,攻击者分配包含UAF/DF漏洞的块时,一般需要连续地分配一组对象,其中包含一个存在漏洞的对象,其余都是无关的对象。

假设这样的一组对象有A个,单个slab包含N个对象,有如下两种情况:

情况①如果A,则不必担心是否会导致填满本个slab,因为slab刚刚创建,仍有完全足够的空间可供分配。容易知道,此时成功率可以达到100%;

情况②如果A≥N,这时候就需要精心构造slab的结构。因为slab刚刚创建而且slab长度已知,所以可通过对象喷射精确把控slab内部的对象个数。

此时必须要借助对象喷射提前布置,以让连续地分配一组A个对象时,最后是恰好覆盖完slab的,如右图所示:

这样一来,无论存在漏洞的块A在哪个slab被释放,也能够让CPU-page-freelist指向其slab,如右图所示。此时申请目标对象T则总是能够被放入相同的位置里面。成功率仍然可以达到100%。

作者给出的缓解方案

针对PSPRAY的缓解机制,作者给出的修复方案是“慢路径索引”方案,核心思想是随机化慢路径分配的上下文,使得攻击者无法通过慢路径这一信息推测内存的分配情况。

定义一个[0,N-1]的常量,称为慢路径索引,其中N为slab中对象数量。

只要慢路径索引==slab的索引值,

不管slab是否被填满,进行一次慢路径分配,产生新slab。于是即使是进行慢路径的分配,空闲列表也是可以处于任何分配状态的:

缓解措施前:慢路径 -> slab内部仅一个obj被分配

缓解措施后:慢路径 -> slab内部有[1,N]个obj被分配

右图伪代码红字部分为作者增添的逻辑。这非常易于实现,判断当前slab的索引值,是否等于内核维护的慢路径索引值。如果slab的索引值等于慢路径索引值,而且CPU-partial表是空的(换言之,目前没有能立刻供使用的空slab)那就会进入慢路径,创建一个新的slab。

这一做法,使得攻击者无法通过测出慢路径的发生,推断实际的内存分配状况。因为此时慢路径可能代表slab任意被填充的状况,即攻击者无法推测内存分配相关信息。

右图展示了慢路径索引方案的实例,slow-path index就是所谓的慢路径索引,一旦cpu-freelist的索引与其相等,如步骤2a,则立刻使用Buddy方法进行新slab分配,并放入cpu-partial等待本轮cpu-freelist使用结束,如步骤3 ,此时cpu-partial上的新slab被赋予到cpu-freelist,并且生成新的慢路径索引。

缓解方案仍然能被绕过

本文提出的慢路径索引缓解方案,其实并没有起到应有的效果,实验仅仅围绕原来的利用手法产生,而这个缓解方案仍然存在被绕过,或者至少,存在仍能够大大提升成功率的可能。作者所述的缓解机制,在一般情况下的效果:

继续从时序侧信道泄露内存分配情况的点出发,实际上作者忽略了一种可能性:如果观察到连续两次分配都触发了慢路径,那就只有两种情况,

第一种情况是,cpu->page到了全新的slab,前一次慢路径分配说明慢路径索引处于slab末尾,而后一次慢路径分配说明慢路径索引处于slab的开头;换言之,这意味着目前的CPU-freelist指向仅仅分配了一个对象的新slab。此时使用PSPRAY同样的手法,便仍能够利用时序侧信道来推断内存分配情况,从而提升攻击成功率。

第二种情况则看起来复杂些。

如果我们假设作者未公开的13行补丁代码里面的逻辑是每个slab都维护一个慢路径索引,而不是全局共享一个慢路径索引的话,而且对于更换已经被用过的cpu->partial到cpu->page后,仍然继续检查它的慢路径索引的话,就会有这种情况产生。否则,第一种情况100%正确。

第一次分配没有触发慢路径分配,原因是cpu->partial非空,但是此时slab耗尽,cpu->page到了已经被分配过对象的slab,但是其恰好又是触发慢路径的那个slab,则此时仍然是两次慢路径分配。只不过,即使在“第一次分配没有触发慢路径分配”这一事件的条件下,恰好如此糟糕的情况,其实是一个在N长度的slab中的N选1问题,故其条件概率仅为1/N,实际上的概率更是微乎其微。

比如,对于obj最少的slab种类:kmalloc-4096,其只有8个obj,那么其利用“两次慢路径PSPRAY”手法,利用UAF&DF的条件概率会下降到7/8,真实的理论概率只会更高。对于比较常用的kmalloc-256等,有32个obj,利用UAF&DF的条件概率会下降到31/32,其实并不是特别严重的下降。

根据以上推论,相信这种稀有的情况,不会改变“两次慢路径PSPRAY”这种新手法能够大大提升PSPRAY缓解措施下的利用成功率的结论。当然这需要再设计一些实验来进行验证。

安全问题的修复是代价与收益平衡的问题,如果因此而去对性能进行“平坦化”来模糊对象分配信息显然是不值得的。所以仍然沿用作者的思路,即允许慢路径与其它路径的显著差异,但让攻击者无法通过慢路径现象猜透对象分配实际情况,以让失败概率维持原来该有的水平,而且在设计缓解机制的过程中考虑前后两次慢路径不应该提供任何信息,同时还应该关注性能和内存开销的问题。

所以如果真的实行这样一种改进方法,至少需要设计以下的RQ:

RQ.1

对普通手法,PSPRAY手法,以及上文提出的“两次慢路径PSPRAY”手法,进行精确程度的测试,并且同样采用作者提出的7个CVE漏洞和3个内核fuzz的漏洞,这些漏洞涵盖了几乎所有的kmalloc-cache以体现本方法的有效性。

RQ.2

同时,应该设置RQ研究改进的缓解方案所带来的对“两次慢路径PSPRAY”攻击精确度的缓解作用,同样涵盖十个漏洞,而且需要比对应用缓解机制以前和以后的漏洞利用成功率,这样才能体现本方法的确能够缓解安全问题。

RQ.3

同时必须设置的RQ是性能和内存开销的测试,必须对应用缓解措施在各个场景,如开机时初始化的场景,I/O密集型场景,CPU计算密集型场景进行性能和内存测试,因为如果内存和性能开销实在太大,那么这个方案就不现实了,即使它提供了足够的安全性。

我认为本方法的改进方向在于,让缓解机制得到完全的随机化。具体而言,可以让检测到慢路径索引值相等,并完成buddy分配后的行为,也变得随机化起来,这样才能避免其整套运行机制被攻击者操控利用。

但是经过一些思考,我认为难点还是如何才能不引入新的绕过方式,因为缓解机制本身的特性也很有可能被利用。而且,一个比较完备的缓解机制,很可能都需要引入较大的内存、性能开销,这时候或许就需要去比对几个比较有效的方案的性能,并且最终敲定影响不是那么大的一个。

评论

  1. 7 月前
    2024-3-19 14:17:48

    呜呜呜,太高端了

    • 博主
      风之子.
      7 月前
      2024-3-20 22:25:37

      不是QwQ选的课的老师逼着看完的,其中有点痛苦的呜呜

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
粤ICP备20015830号