Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

Gollum: Modular and Greybox Exploit Generation for Heap Overflows in Interpreters

作者:Sean Heelan, Tom Melham, Daniel Kroening

单位:University of Oxford

出处:CCS 2019

资料:Paper


1. 介绍

在本篇文章中,作者实现了第一个用于解释器堆溢出漏洞的自动化漏洞利用生成 (AEG) 方案,命名为 GOLLUM。作者用PHP和Python的10个不同漏洞进行了实验,其中5个漏洞都没有公开的Exploit,都能顺利生成可用的Exploit。

作者的贡献:

  1. 使用了纯灰盒的方式实现,不需要符号执行或者白盒分析,这个方法依赖于从现有的测试文件中提取信息,进行轻量级插桩和Fuzz。
  2. 堆布局的Lazy Resolution。
  3. 介绍了一个解决堆布局问题的算法,相比现有算法更高效。

作者选择解释器漏洞作为目标的原因是,从安全角度来说,解释器是存在内存安全漏洞的,从AEG研究来说,相比于之前的工作,解释器是一个不同类型的程序,现有的AEG大部分是针对有文件解析的命令行工具或者系统。现有的大部分AEG没法用于解释器漏洞上,因为解释器的状态空间太大,符号执行不适用。

选择堆溢出漏洞的原因是,堆溢出是最普遍的一类漏洞,并且现有AEG工作对这类漏洞的研究还不是很充分。要利用堆溢出漏洞,需要攻击者事先了解堆的布局,之前已经有在已知堆布局的条件下的堆溢出漏洞AEG工作,作者的工作将这个完整过程自动化了。

2. 设计

没有前提假设的AEG在现在显然还是一个开放的难题,这个工作也给出了一些假设:

  1. ASLR已经事先被绕过。
  2. 没有部署CFI。
  3. 堆分配器的行为是确定的,初始状态可被预测。

GOLLUM的输出是一个被解释器执行后,可以执行Shell的目标程序。Exploit Primitive包括控制流劫持内存写

一般地来说,已知一个堆溢出漏洞后,要实现Exploit Primitive,需要做的事情:

  1. 找到一个可以污染的目标结构体,并且保证这个结构体的实例与发生溢出的对象是相邻的。
  2. 保证被污染后的这个结构体可以被攻击者进一步操作。

GOLLUM的整个工作流程如下图所示。

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled.png

2.1 CVE-2014-1912

Python bug tracker里提供的漏洞触发程序如下:

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled%201.png

以这个漏洞为例,GOLLUM的工作流程:

2.1.1 导入Trigger脚本

这一步需要事先知道Trigger脚本的两个信息:

  1. 哪一个变量的内存会发生溢出,以及是否这个变量的长度可以被修改,如果可以修改,最大长度是多少?
  2. Trigger脚本中导致触发的行号。

2.1.2 整合Trigger脚本和Tests脚本

GOLLUM需要知道如何在堆上创建值得污染的堆对象,以及如何去操作它。所以利用了目标解释器自带的测试用例脚本Tests。Test脚本越小越好,需要能创建包含指针的堆对象。

PHP的每个Test文件都直接测试了PHP单独的一个小功能,Python的Test则比较麻烦,都是测试一整个子系统的(也就是会有多余的操作),不能直接拿来使用。好在是Python的这些Test文件结构都比较好。作者对python的Test文件进行了些预处理,把单独的测试都分离了出来(这个过程是启发式的,不能全分离出来)。

得到了Trigger和Test文件后,进行整合。最终的Exploit Primitive需要分配堆对象的代码,触发堆溢出的代码,以及使用被污染的堆对象的代码。Test提供了第一个和第三个部分的代码,Trigger提供了第二部分的代码。具体的插入的位置是用启发式的方法去生成的,最终会得到很多新的输入程序

2.1.3 探索堆布局

新的输入程序都会用ShapeShifter来执行,ShapeShifter使用了一个自制的堆分配器,从而可以检测堆溢出的发生,当检测到发生后,ShapeShifter会记录此时所有的堆上存活的对象。ShapeShifter使用了libdislocator这个库,这个库会让被分配的堆块的最后一个字节以页对齐,然后会在这后面分配一个页,这个页的权限是不可访问的,这样一旦溢出就会崩溃了。ShapeShifter有两种运行模式:

  1. 在溢出的时候去记录当时存活的堆对象,会给每个对象进行标记
  2. 另一个是在指定的堆布局下运行程序。输入是两个对象的标记,分别是Src和Dst,Src会被分配在Dst的前面(相邻)。

每一次的新生成的输入程序都会先用ShapeShifter的第一个模式去跑,记录所有存活的分配,然后会用第二个模式去跑,记录崩溃信息。这样得到的输入程序和记录信息的二元组称为Candidate Primitive。

2.1.4 Primitive分类、动态确定输入输出的关系

这一步需要确定Candidate Primitive里可用的部分。这部分就是经过一系列检查。

  1. 检查崩溃时的指令是否修改了程序的控制流,来确定这是否是一个IP-hijack Primitive。如果崩溃指令是一个内存写,则认为是一个Mem-write Primitive。
  2. 确定是哪部分的内容修改了关键寄存器,例如如果是IP-hijack Primitive,只需要比对一下IP寄存器的值即可。这里可以用动态污点分析,但是比较影响性能,作者采取的方法是修改输入,看寄存器的值的变化来确定。

这一步的输出是分类过的Primitive,以及每个Primitive记录的相关信息。

2.1.5 生成Exploit

这一步将Primitive进行变换,生成Exploit。分两步完成:

  1. check(c, …)。确定是否可以进行变换。
  2. transform(c, …)。进行变换。

GOLLUM现在提供了两种Primitive Transformer,一种是给IP-hijack用的,另一种是给Mem-write用的。目标都是得到一个/bin/sh的shell。

对于IP-hijack,具体的控制流跳转目标,作者用的是CTF竞赛中常用的One-gadget payload。如下所示是check函数的伪代码。就是看一下崩溃时的条件满不满足One-gadget的条件。

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled%202.png

如下所示是Transform函数的伪代码,就是更新一下原来的payload里的可以控制IP的部分,改为One-gadget的地址。

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled%203.png

这一步完成后会再运行一下生产的输入程序,看能不能执行/bin/sh。最终的输出则是一个二元组 (Exploit, HeapLayout)。

2.1.5 解决堆布局问题

作者在之前的Shrike这个工作上进行了改进,Shrike是通过在Exploit里不断随机插入代码片段,来找到一个目标堆布局的解,并且这个过程不是很自动化。

Shrike要求使用者在Exploit里插入一些指示符 (Directives) : HEAP-MAINP, RECORD-ALLOC, REQUIRE-DISTANCE。

这些指示符指导Shrike哪些地方是可以插入堆操作代码,需要记录的堆分配,以及这些分配地址之间的距离。如下图所示是一个例子。

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled%204.png

GOLLUM自动插入这些Directive。采用遗传算法解决堆布局问题。

3. 实验

解决堆布局问题所用的实验环境:

  • 80 Intel Xeon E7-4870 2.40 GHz cores
  • 1TB of RAM
  • 40 concurrent analysis processes

Primitive寻找时所用的实验环境:

  • 6 Intel Core i7-6700HQ 2.60 GHz cores
  • 16 GB of RAM
  • 4 concurrent analysis processes

RQ1 : GOLLUM是否能比Shrike更高效地解决堆布局操作问题?

使用5个公开的PHP漏洞 : CVE2013-2110, CVE-2015-8865, CVE-2016-5093, CVE-2016-7126 and CVE-2018-10549。GOLLUM能更好地解决堆布局操作问题。

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled%205.png

RQ2 : GOLLUM是否能为Real-world的解释器漏洞生成Exploit?

如下图实验结果所示。GOLLUM能为这10个漏洞都生成Exploit。

Gollum%20Modular%20and%20Greybox%20Exploit%20Generation%20for%20/Untitled%206.png