Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

KOOBE: Towards Facilitating Exploit Generation of Kernel Out-Of-Bounds Write Vulnerabilities

作者:Weiteng Chen, Xiaochen Zou, Guoren Li, Zhiyun Qian

单位:UC Riverside

出处:USENIX Security 2020

资料:Paper

1. 介绍

现有的关于Linux内核漏洞利用自动生成的工作都是关于UAF漏洞的,这篇文章的工作针对OOB写漏洞(Out-of-bounds memory write),作者将这个工作命名为KOOBE。作者对17个最新的Linux内核OOB漏洞进行了分析(其中5个有公开的利用代码)。KOOBE成功生成了11个漏洞对应的利用策略,这些利用策略之后可以拿来构建完整的利用代码。

研究的出发点:

  1. 不同的OOB漏洞可以有不同的Capability。
    1. 最远能写到哪里?
    2. 可以写多少字节?
    3. 可以写什么值?
  2. Linux内核层的漏洞利用相比于用户层,有一个特点:需要通过系统调用来调用内核态的代码,触发内核漏洞从而达到权限提升的目的。

假设:KASLR、SMEP、SMAP等内核态保护机制的绕过,与本文的工作是相互独立的。

本文沿用了Revery这个工作中用到的一些术语:

  • 漏洞点 (Vulnerability point) :PoC代码中漏洞触发的位置
  • 漏洞对象 (Vulnerable object) :OOB漏洞发生的源对象
  • 目标对象 (Target object) :篡改数据的目标对象

2. 背景

CVE-2018-5703为一个类型混淆导致的OOB写漏洞,如下所示为内核中漏洞代码的简要形式。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled.png

如下为利用堆风水将目标对象分配到漏洞对象附近的简化版PoC。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%201.png

如下所示是CVE-2016-6187和CVE-2017-7184的简化版的代码。CVE-2016-6187是能溢出一个NULL字节,CVE-2017-7184的Capability是一次写一个bit。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%202.png

作者将人工的堆OOB漏洞的利用细分为了如下几步:

  1. 漏洞Capability提取:由Fuzzer生成的PoC通常不能直接利用(可能是往指针写入了随机值或者修改到了系统数据导致崩溃),需要进行精心修改。
  2. 堆风水。将漏洞对象和目标对象分配成空间相邻的状态。
  3. 目标对象选取。函数指针、数据指针、非指针(例如cred结构体里的uid、或者引用计数)。
  4. 生成利用代码,劫持控制流。
  5. 绕过Linux内核防御措施:由于这些防御措施的绕过跟本文的工作比较独立,因此不用考虑。对KASLR的绕过,可以用独立的一个内存泄露的漏洞来完成,也可能可以用CPU测信道漏洞如Meltdown、Spectre、RIDL、ZombieLand等方法。绕过SMEP,可以通过ROP/JOP的方式。绕过SMAP,在控制了数据指针的情况下,可以利用physmap来实现。将控制流劫持再升级为任意代码执行在KELPER这个工作中已经有研究。

3. 设计

如下所示,KOOBE的输入是PoC,最终输出的结果是Exploit

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%203.png

3.1 漏洞分析

输入为PoC文件,目标是发现所有的漏洞点以及漏洞对象。由于KASAN的信息不能保证提供完全的漏洞点以及漏洞对象。因此KOOBE在执行PoC的时候,会结合符号追踪和KASAN,来获得更详细的内存操作信息。

如下所示是CVE-2016符号化以后的PoC(传给S2E分析)

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%204.png

如下所示是漏洞分析输出的一个report,包含了漏洞对象以及漏洞点的信息。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%205.png

3.2 Capability摘要

作者认为一个OOB漏洞的Capability就是一个漏洞点可能得到的所有OOB写的集合。

文中给出的Capability的定义如下。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%206.png

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%207.png

如下所示是前面的例子中的Capability示例。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%208.png

3.3 Capability探索

同一个漏洞,不同的执行路径可能导致不同的漏洞点,从而可能有很多潜在的Capability。但是一个PoC只能有一条执行路径,因此作者设计了Capability制导的Fuzzing。

3.4 可利用性评估

在获得了Capability后,开始在事先搜集好的目标对象的Database里寻找合适的目标对象,如果能找到,就进行符号求解,然后进入下一步地利用程序生成。这一步还需要做的事情是Capability的组合,例如CVE-2017-7184,一次只能写一个bit,但是实际上每次写一个bit也能将

如下所示是输出的结果,已经对符号值进行了求解。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%209.png

3.5 Exploit Primitive生成

只得到Exploit Primitve,不会生成完整的提权代码。

如下为得到的一个最终能劫持控制流的Exploit Primitive示例。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%2010.png

4. 实现

作者基于syzkaller、符号执行框架S2E、二进制分析引擎angr实现了一个原型。

对于目标对象Database的建立,作者是处理了Linux内核里的所有结构体,取出了总共2615个有Critical data的结构体。找出了结构体后,还需要获得如何使用这些结构体的信息,例如如何分配,如何触发解引用等,为了解决这个问题,作者在LLVM Pass上实现,建立整个内核的Call graph进行分析。还要确定参数如何设置才能触发目标对象的分配和解引用,这个问题作者基于了SLAKE这个现有工作。

5. 评估

用17个Linux内核堆OOB漏洞的PoC进行实验。7个来自CVE数据库,10个来自syzbot。

实验环境:Ubuntu 16.04 system running on a desktop with 16G RAM and Intel(R) Core i7-7700K CPU @ 4.20GHz * 8

如下所示是实验的结果,大部分都能生成可以使用的Exploit,能成功为6个没有公开Exploit的漏洞生成可以使用的Exploit。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%2011.png

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%2012.png

时间开销如下所示。时间开销比较大的部分在Capability探索里的Fuzz上,符号追踪和求解的开销都很可观。

KOOBE%20Towards%20Facilitating%20Exploit%20Generation%20of%20K/Untitled%2013.png