论文题目:Automatic Generation of Data-Oriented Exploits
这篇论文来自于Usenix 2015
文章目录
简介:
由于针对控制流劫持的防御机制在广泛应用,控制流导向的漏洞利用变得更加复杂了。一个备选方案是,针对非控制数据进行攻击,就无需转移控制流。虽然数据流攻击可以造成严重的危害,但是目前没有系统自动化构建它们的方法。作者设计了一种新的技术叫data-flow stitching, 可以系统地去找程序中的数据流来生成数据流利用。作者构建了一个工具叫FLOWSTITCH,可以在linux和windows的二进制文件上运行。在实验中,发现FLOWSTITCH可以在8个真实有漏洞应用中,自动化构建16种未知和3种已知的数据流攻击。所有的利用都考虑细粒度的CFI和DEP,其中10个也考虑了ASLR。构建的利用可以造成严重的危害,比如敏感信息泄露,提权。
背景
研究意义
在内存错误利用上,攻击者经常去实现任意代码执行,而这通常是终极目标。这些攻击通常通过利用内存错误来劫持程序控制流。然而这种基于控制流的攻击,包括代码注入和代码复用,可以被CFI,DEP,ASLR等防御机制所阻挡。最近这些机制得到了广泛的认可,并被应用到一些操作系统,编译器等地方,使得基于控制流的攻击更难了。
然而,控制流攻击并不是唯一的内存利用方式。内存错误同样可以通过污染非控制数据来实现数据流攻击。数据流攻击可以破坏程序的数据或者泄露关键数据。心脏滴血漏洞就是一个敏感数据泄露,而控制流没有改变的例子。
虽然数据流攻击理论上很简单,但是实际上的数据流攻击都只是破坏非控制数据。目前没有系统的方法来识别和构建数据流攻击。
关键技术和挑战
关键思路是如何高效搜索一条新的数据流边,并且加入到G‘中,从而在vs和vt间创建数据流路径。
Challenge1:搜索空间很大。一个2D-DFG中有很多数据流和一大堆节点。比如,在SSHD攻击中有776源节点和56个目标节点。由于我们经常需要分析去连接每对节点,因此寻找一条可行路径的搜索空间是巨大的。
Challenge2:对于内存布局知之甚少。大多数现代的操作系统默认开启ASLR。数据内存区域的及地址,比如栈或堆,是随机化的,因此很难去预测。
Challenge3:复杂程序的路径约束。一个成功的数据流攻击导致漏洞程序执行内存错误,创建了一条缝合边,继续运行而没有崩溃。这要求输入要满足所有的路径约束,遵从程序控制流完整性的约束,并且避免非法的内存访问。
研究问题
检查程序是否可以被数据流攻击利用,如果可以,自动生成数据流攻击。
贡献
- 理论化了数据流缝合,提出了一种方法来系统化地构建数据流攻击
- 开发了一个数据流攻击自动化的工具FLOWSTITCH
- 利用通用的内存漏洞构建数据流攻击是可行的,并且能够绕过控制流防御机制。
方法
数据流攻击的示意图,a图是正常执行的过程。b图是实现了攻击,攻击者将pw1变量变为了b2,然后后面的操作从b2读取0,赋值到target。导致target变为0。如果target是setuid位,就可以进行提权了。
系统框架如下:
输入:后面的两个输入都可以利用已有的符号执行工具构造(BAP,SAGE)
- 内存错误的程序
- 一个触发错误的输入
- 程序的正常输入
构造数据流攻击的五个步骤:
- 为给定程序产生一个执行追踪。(有benign trace和error-exhibiting trace)
- 识别内存错误的影响,并产生路径约束(从程序输入到达内存错误的路径)
- 使用良好追踪来做数据流分析和敏感数据识别
- 从识别的敏感数据流中选择候选缝合配件
- 检查用内存错误创建的新的边的可行性,并验证利用
内存错误影响分析
FLOWSTITCH分析error-exhibiting trace来求出内存错误的影响I。主要是从两个方面来评估其影响:
- 时间影响:什么时间内存错误会发生
- 空间影响:由于内存错误可以被覆盖的内存范围(这个好像别的文章也有提过)
由于程序的逻辑限制了攻击者能够访问的内存范围。为了识别内存错误指令的空间影响,使用动态符号执行从错误踪迹中产生一个符号公式。满足公式的输入表示执行到这个地方的内存错误指令是在意料外的地址上。
安全敏感数据识别
有四种数据是值得缝合的:
- 输入数据:在追踪生成时,执行污点分析,认为给定的输入是一个外部污点源。
- 输出数据:识别一系列程序的sink,比如send,printf。用在sink里的参数就算输出数据。
- 程序密钥:
- 许可标志位
将后两者数据分为两类:程序特定数据和通用数据。对于程序特定数据,FLOWSTITCH接受用户设定来找到程序特定数据。对于通用数据,用以下方法来推出:
- 系统调用参数:从执行路径中识别所有的系统调用参数,比如setuid,unlink
- 设置数据:将设置文件视为污点源,使用污点分析来追踪设置数据的使用
- 随机化数据:根据设置和检查canary的指令来识别stack canary,如果他们不在确定的内存区域,则识别出随机化的地址
识别出确定的内存区域是使用带有确定地址的stitch。首先检查程序的二进制来找出不会在运行时随机化的内存区域。如果程序位置独立的,所有的在二进制header里的地址都是确定的。FLOWSTITCH收集所有可加载的部分,然后获取一个确定内存集合D。接着去搜索良性执行路径中所有内存写指令(写数据到确定地址处),进而识别存在这个区域的数据。
由于敏感数据的功能性,我们预先定义攻击的目的。比如,setuid的参数改为0,就能够提权了。或者将web服务器的根目录改为root目录。
stitch 候选选择
基于以下两个原则来产生stitch:
- 先从一条边的stitch开始尝试。试完了一条边再试多条边的。最多只试到四条边。
- 认为在地址复用前的stitch的地址是确定的。在穷尽了确定地址和复用地址的搜索空间后,FLOWSTITCH继续用准确地址在benign追踪里搜索stitch。
候选过滤
定义了stitchability constraint来表示以下三种约束:
- 到达内存错误指令的路径条件
- 继续目标流的路径条件
- 控制数据的完整性
使用符号执行来产生stitchability constraint,然后送到SMT去求解。如果找不到一个输入满足约束,就跳到下一条stitch边去。如果存在的话,输入将会用来执行,来实现数据流攻击。由于符号执行在实现上的准确性,约束可能是不完整的。所以可能会产生一些输入导向不同的路径。所以最后还需要验证一下。
实现
- 踪迹生成:BAP框架,Pin来动态二进制插桩记录程序执行状态
- 数据流生成:使用污点信息来获取数据流。获取敏感数据的数据流,使用前后向切片来定位到相关的指令。
- 约束生成和求解:BAP+Z3 SMT求解器
- 路径约束
- 影响约束
- CFI约束
结果
有效性
对8个程序,不同的漏洞,进行了测试,都能生成数据流攻击。
生成的19种数据流攻击的情况
搜索空间的减少
可以从Table3的后四列看出来,节点个数减少了很多。
性能
大部分都可以在10分钟内完成,可以说是相当快了。
相关工作
数据流攻击相关工作
已经有相当多的工作提高了CFI的可行性,使得控制流劫持变得很难。因此,数据流攻击就是另外一个很好的选择。数据流攻击在这篇文章发表之前,已经出现了10年。来源于Usenix 2005的这篇论文:Non-Control-Data Attacks Are Realistic Threats.
漏洞自动化利用生成
APEG,通过识别打过补丁和未打过补丁的二进制来产生输入触发这个不同点。AEG自动化生成真实的利用,来获取一个shell。Felmetsger提出的是针对web应用的利用生成。前人的工作主要都是基于控制流劫持的利用。FLOWSTITCH是最早的自动化生成数据流攻击的工具。
数据流攻击的防御
数据流攻击可以被数据流完整性(DFI)所防御。现有的工作通过动态信息追踪或合法内存修改指令分析来加强DFI。终极防御是在第一步加强内存安全,比如Cyclone,CCured,引入了类型安全的C语言。带CETS的SoftBound使用边界检查来检测胖指针。Cling通过类型安全内存复用来加强内存空间安全。数据流攻击的防御需要一个完整的内存安全防御。
总结
- 应该是第一篇数据流自动化攻击绕过防御机制的论文。
- 这篇论文的作者在后一年也发表了DOP。