APP下载

基于S2E的Use-After-Free漏洞检测方案

2016-05-09王轶骏

计算机应用与软件 2016年4期
关键词:指针插件漏洞

冯 震 聂 森 王轶骏 薛 质

基于S2E的Use-After-Free漏洞检测方案

冯 震 聂 森 王轶骏 薛 质

(上海交通大学信息安全与工程学院 上海 200240)

Use-After-Free漏洞是由程序试图操作悬垂指针引起的。该类型漏洞近年来在针对浏览器客户端的攻击中变得愈发流行。提出一种针对Use-After-Free漏洞的检测算法,并据此实现检测方案UAFChecker。UAFChecker基于开源的多路径软件分析平台S2E,它通过挂钩关键的堆内存操作函数监控指针的生成,使用反汇编引擎BeaEngine在汇编层上跟踪指针的传播,通过收集和分析指针信息来检测漏洞。实验结果表明,配合Fuzzing技术UAFChecker成功定位和分析出IE8浏览器中存在的多个未被公开的Use-After-Free漏洞。

Use-after-free漏洞 漏洞检测 悬垂指针 污点传播 符号执行

0 引 言

近几年来,各种应用软件和操作系统组件曝出UAF(Use-After-Free)漏洞的报道频频见诸报端。CVE(Common Vulnerabilities and Exposures)数据库所记录的UAF漏洞的条目,自2008年开始几乎以每年翻一番的速度增长。而在各项黑客大赛中,各国安全团队也经常利用UAF漏洞攻破包括IE、Chrome和Safari在内的主流浏览器客户端。UAF漏洞已经引起众多安全人员和黑客们的关注。本文以S2E[1]为基础设计并实现针对二进制程序UAF漏洞的检测方案,介绍该方案的检测算法、基本架构和设计细节,并对其进行了测试和评估。

1 S2E平台介绍

S2E是选择性符号执行的英文缩写,是面向二进制程序的多路径符号执行的软件安全测试平台[2]。S2E基于QEMU、KLEE和LLVM。其中,QEMU作为虚拟机运行目标程序,KLEE用于符号执行,而LLVM进行动态二进制翻译。S2E能够只对用户关心的目标代码实施符号执行,而对系统内核代码实施具体执行,从而有效解决了路径爆炸问题[3]。

S2E提供了扩展性良好的插件系统,用户可以按需编写自己的插件。S2E自带五类插件供用户使用,分别是系统事件监控插件、执行跟踪插件、选择性插件、分析插件和混合插件。本文的检测方案就是以S2E插件的形式实现的。

2 问题描述

UAF漏洞涉及两个事件:生成悬垂指针和使用悬垂指针。两个事件在时间点上一般是分开的。

2.1 漏洞解释

当所指向的对象被释放或者回收,但是对该指针没有作任何修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称为悬垂指针(也叫迷途指针)。图1展示了悬垂指针的生命周期。在t创建对象1被释放,从而生成了悬垂指针。在t销毁之前,如果程序又使用了悬垂指针,就会导致UAF漏洞[4]。此时,悬垂指针指向的内存,或者未被分配,或者已经另作他图,并非程序原本期望的行为。攻击者可以利用UAF漏洞读取私密信息,重写敏感信息,甚至执行任意代码[5]。

图1 悬垂指针生命周期

2.2 技术现状

分析程序可以分为静态和动态两类。静态分析程序能确保完备性但误报较高。动态分析程序具体使用的方法则较为多样,大致分为三类:影子内存,即将程序所使用的内存映射到可控内存;动态插桩,即在指令之间插入分析代码;Debug Allocators,即通过HOOK分配函数,强制分配冗余数据。动态分析的局限在于代码覆盖率会比较低。

动态插桩是目前最为流行的动态分析技术。在应用该技术检测UAF漏洞时,具体的检测算法可分为空间算法和时间算法。空间算法指的是处理悬垂指针指向的堆内存(例如将其设置为无访问权限或添加隔离区),从而确保目标程序在试图访问该内存时出错。这种算法有两个局限:一是只能在直接访问堆内存即发生UAF漏洞时触发;二是无法检测堆内存被重分配的情况。时间算法基于一个直觉,即长期存在的悬垂指针是不安全的。时间算法首先设置生命阈值,然后记录和跟踪所有悬垂指针的生命周期,并在该周期超过阈值时发出预警。时间算法能在早期检测出悬垂指针,其代价是较大的开销和一定的误报率。

2.3 检测原理

我们的检测方法同样采用了动态分析的插桩技术。为了提高代码覆盖率,首先我们选择S2E作为开发平台,发挥其强大的多路径符号执行能力;而在输入复杂的情况下,通过和Fuzzing技术配合缩小需要符号化的数据。

然后,我们重新设计了UAF检测算法,基本流程是:HOOK堆管理API,以监控堆内存的分配和释放;跟踪指针的传播,维护指针和堆内存的映射关系;在堆内存被释放时把与其对应的所有指针清零置空。下面用一段示例代码予以说明:

0A*a=newA();moveax,dwordptr[b]1B*b=newB();movecx,dwordptr[eax+4]2b->pa=a;moveax,dwordptr[ecx]3deletea;movedx,dwordptr[eax+4]4a=NULL;calledx5b->pa->f1();

首先要说明的是右侧的汇编语句和左侧的C++语句并非一一对应,而且语句之间可能省略了部分代码。如果a所使用的堆内存被再分配,而且恰好也是一个包含虚函数的类对象,那么空间算法可能无法检测出该UAF漏洞,结果是代码调用了非预期对象的方法。如果再分配的目标只是普通的对象,那么空间算法可能在汇编语句2、3、4报错,这取决于再分配后堆内存的内容。如果堆内存没有再分配,那么空间算法可能在汇编语句3和4报错。

而在任何情况下,我们的检测算法都能确保程序在汇编语句2报错。这是因为指针清零后,无论是读写成员属性,还是执行成员方法,任何试图对该指针的访问都会被拒绝。

检测算法的关键在于清零置空和释放堆块对应的所有指针,因此需要可靠的污点跟踪功能,以获取指向释放堆块的所有指针。该算法在一定程度上提前了UAF漏洞的发现时机,提高了漏洞的发现概率,同时完全解决了堆内存再分配带来的问题。而在具体实现检测方案时,我们还结合了空间算法,以克服可能存在的指针遗漏问题。

3 检测方案

以S2E平台为基础我们设计和实现了针对目标二进制程序中UAF漏洞的检测方案,我们将其命名为UAFChecker。

3.1 架构概述

UAFChecker在功能逻辑上可以分为反汇编模块、堆内存监控模块、指针传播跟踪模块和信息分析模块四部分,基本架构如图2所示。

图2 UAFChecker架构图

反汇编模块负责获取指令寄存器EIP对应指令的汇编代码;堆内存监控模块通过挂钩堆内存操作函数监控堆的分配和释放,也就是正常指针(堆分配)和悬垂指针(堆释放)的生成;指针传播跟踪模块是基于反汇编模块得到的汇编代码,在汇编层上实现的一套污点跟踪系统[6],指针是污点源;信息分析模块收集和分析与指针相关的信息,并把分析结果写入到日志文件中。

3.2 模块分析

3.2.1 反汇编模块

我们把开源的反汇编引擎BeaEngine[7]编译到S2E中。利用EIP地址获得对应汇编指令。这引入了非常可观的开销,几乎导致QEMU一直处于假死状态。为此,我们设置数目为4K的反汇编指令Cache,用于缓存至多4K条汇编指令,显著提高了反汇编效率。反汇编模块会分析汇编指令的操作符和操作数,是其他三个功能模块的基础。

3.2.2 堆内存监控模块

UAFChecker使用FunctionMonitor(S2E自带插件)挂钩了RtlAllocateHeap和RtlFreeHeap两个Windows API。几乎所有的堆分配函数最终都会使用这对API,例如malloc/free和new/delete,因此挂钩RtlAllocateHeap/RtlFreeHeap后也能监控到这些函数的调用。另外,IE浏览器在处理BSTR字符串时使用和维护了一个空闲堆块的缓存,这和Windows操作系统的快表结构很相似[8]。与此相关的API是AllocCachedMem和FreeCachedMem,具体细节会在第4节分析说明。

3.2.3 信息分析模块

信息分析模块共维护了三个队列:分配队列、指针队列和反向队列。其中,分配队列记录了所有分配的堆内存块;指针队列记录了所有指针;而反向队列记录了指向某一堆内存的所有指针,用于查询和清零悬垂指针。

在堆块被释放时执行下述操作:将反向队列中的指向该堆内存的所有指针清零置空,并将堆内存数据区填充0xcc(中断int 3的机器码)。一方面,如果程序试图访问某悬垂指针,因为其指向的地址是0,所以会发生非法访问;另一方面,如果程序执行了call some_address而some_address位于释放堆块中,因为其数据一定是0xcccccccc,故程序会崩溃。

3.2.4 指针传播模块

该模块是UAFChecker的核心部分,检测算法高度依赖该模块的准确性和完备性。指针传播模块在反汇编模块提供的汇编层上跟踪指针的传播,并向信息分析模块提供输入。

我们首先定义了污点(指针)结构体,包括start、offset和ext等成员。出于性能的考虑,几乎所有的字节级的污点跟踪程序都只能判断某个字节是否是污点,即把所有的污点数据等同处理[9]。而我们使用start和offset,能够提供污点源的精确位置:start表示堆内存的起始地址,offset表示相对偏移。

然后定义指针传播的若干规则:MOVE、ADD、XCHG、LEA、CLS和NOP。X86指令集中的所有指令都会应用某种规则或组合,并以模拟执行的方式传播污点[10]。表1列出了部分指令和规则的对应关系。

表1 x86指令、抽象和规则

和污点传播一样,指针传播也要解决线程切换和CPU状态切换导致通用寄存器的内容不一致的问题[11]。而与之不同,且更为关键的问题是如何识别堆管理结构。

测试的目标软件是Windows XP上的IE 8浏览器,因此我们要关注FreeList、LookasideList以及IE自身使用的堆管理结构。这些数据结构会记录空闲堆块信息,相关指针无须跟踪,更不能清零,否则会引发异常。

FreeList是双向链表,所以能够根据释放堆块得到前趋结点和后继结点,进而计算出记录指针的位置。LookasideList是单向链表,因此无法直接得到前驱结点,但是可以利用快表中至多存在一个结点指向释放堆块这一事实确保排除相应指针。而在处理IE浏览器内部的缓存数据结构时,我们采用了攻击者编写EXP时才会使用的技巧,即通过预分配清空所有缓存。最终我们设计了如下算法:

算法1 堆管理结构处理算法。

输入:释放堆块

输出:记录释放堆块的指针被删除

1) 调用flushCache方法,强制使用RtlAllocateHeap和RtlFreeHeap;

2) 获取释放堆块对应的反向队列中的末尾结点;

3) 将末尾结点从指针队列和反向队列中删除;

4) 读取释放堆块的前两个DWORD,记为dw1和dw2;

5) 分别比较dw1+4和dw2的内容与释放堆块的地址,如果相等就从指针队列和反向队列中删除。

步骤1)中的flushCache方法通过分配一系列的堆块,确保IE分配和释放堆内存时使用HOOK的API。步骤3)删除的结点可能存在于FreeList或LookasideList中,该步骤能够确保快表中的记录指针不被指针传播模块跟踪。而步骤4)和5)用来检测释放堆块被添加至FreeList的情况,能够删除可能记录在空表中的指针。

4 方案评估

在正式测试IE浏览器之前,我们首先进行了基准测试,用来检测UAFChecker的基础性能。

4.1 基准测试

基准测试程序集中的样本由SAVG(Systems Analysis and Verification Group)和LAV(一款开源的静态程序错误检测工具)提供[12]。在输入比较简单的情况下,UAFChecker能够充分发挥S2E多路径符号执行的优势,将输入符号化并约束求解关键路径,检测出可能存在的UAF漏洞。测试结果如表2所示。

表2 基准测试结果汇总

表中DF和ML分别表示Double Free和Memory Leak。上述测试结果和基准测试集的说明完全一致,无误报和漏报情况,说明UAFChecker在输入较简单的情况下表现良好。更重要的是,这说明指针传播模块功能正常,确实能够准确地跟踪和监控指针的生成和传播。

4.2 测试IE浏览器

实验环境为Windows XP SP3全补丁,IE8.0.6001.18702,VMWare Workstation 8.0.2 build-591240虚拟机环境。

浏览器的输入是HTML文件,文本结构复杂,不宜将其完全符号化直接测试。因此我们首先使用Fuzzing工具生成HTML样本,然后再使用UAFChecker进行测试。使用这种方案我们得到了大量Crash文件,目前已经分析和确认了3处UAF漏洞,如表3所示。

表3 UAF漏洞信息汇总

Crash文件名是Fuzzing工具自动生成的。上述漏洞还没有被公开,都是IE8的0-day。有趣的是,这三个漏洞都和节点操作有关,有相同的“漏洞框架”:Javascript代码块首先修改DOM树结构,如appendChild和applyElement。这些语句执行时修改了DOM树结构,但是新创建的DOM元素或被修改的元素并未马上得到渲染。接着,后续代码把这些元素的属性修改为已渲染,但浏览器不知道元素的释放情况,也不会更新节点关系,从而导致Use-After-Free。我们已经分别为上述漏洞编写了EXP,成功地弹出计算器,即能够实现任意代码执行。

值得一提的是,微软6月发布的补丁引入了Isolated Heap,7月发布的补丁又引入了Deferred Free,这两个补丁瞬间提高了UAF漏洞的利用门槛。Net Market Share今年5月的调查显示,虽然微软早已放弃了对XP系统的支持,但XP的市占率仍高达29.23%。绝大部分XP用户不会下载和安装这两个补丁,所以上述三个漏洞仍然具有很大的威胁。而且,三个漏洞自身没有被补掉,只是目前比较流行的漏洞利用技术难以克服新的安全机制而已[13]。

4.3 相关工作

SEA[14]是Symbolic Exploit Assistant的缩写,采用Python编写,目标是辅助发现二进制程序中的各种内存错误。SEA为面向二进制程序的分析工具提供了设计出色的架构模型。目前SEA只支持分析目标程序的REIL码,而且要求输入文件记录了目标程序所有的堆内存操作。VSA[15]是一款针对UAF漏洞的静态分析工具,因此具有静态分析的优势和缺陷。Undangle提出和实现了时间算法,并成功地发现了Firefox 3中的6处危险指针,其分析效率和分析效果与参数设置密切相关。UAFChecker的优势一是利用S2E的多路径符号执行能力提高了代码覆盖率,二是检测算法解决了堆内存再分配的问题,并提高了UAF漏洞的发现概率。不过,UAFChecker对指针传播模块的依赖度较高,而后者的准确性和完备性难以保证,由于采用了S2E,UAFChecker的开销也比较大。

5 结 语

本文基于S2E平台设计和实现了针对UAF漏洞的检测方案UAFChecker。UAFChecker采用Cache和Hash算法极大地减少了使用BeaEngine反汇编带来的开销,然后在汇编指令层上实现了真正的字节级的指针传播系统。漏洞检测算法在一定程度上提前了UAF漏洞的发现时机,提高了漏洞的发现概率,并完全解决了堆内存再分配的问题。配合Fuzzing工具,UAFChecker成功地在IE8中发现了多个未被公开的UAF漏洞。尽管UAFChecker已经能够基本满足我们的需求,但是它在效率和完备性方面还存在诸多不足。在未来,我们将主要在如下三个方面开展研究工作:

1) 在S2E的中间语言层上重新实现指针传播模块,从而能够完全规避反汇编引入的开销。

2) 扩展和优化检测算法,一种可能的途径是结合时间算法进一步提高UAF漏洞的发现概率。

3) 优化和改进堆管理结构处理算法。

[1] Vitaly Chipounov,Volodymyr Kuznetsov,George Candea. S2E: A Platform for In-Vivo Muti-Path Analysis of Software System[C]//New York: Newsletter ACM SIGPLAN Notices - ASPLOS ’12,2012,47(4):265-278.

[2] Edward J Schwartz,Thanassis Avgerinos,David Brumley. All You Ever Wanted to Know about Dynamic Taint Analysis and Forward Symbolic Execution (but Might Have Been Afraid to Ask)[C]//Washington DC: Proceedings of the 2010 IEEE Symposium on Security and Pricacy,2010:317-331.

[3] 王学,李学新,周智鹏,等.S2E测试平台及并行性性能分析[J].信息网络安全,2012(7):16-19.

[4] Victor van der Veen,Nitish dutt-Sharma,Lorenzo Cavallaro,et al. Memory errors: the past,the present and the future[C]//Berlin,Heidelberg: Proceddings of the 15th international conference on Research in Attacks,Intrusions,and Defenses,2012:86-106.

[5] Juan Caballero,Gustavo Grieco,Mark Marron,et al. Undangling: Early Detection of Dangling Pointers in Use-After-Free and Double-Free Vulnerabilities[C]//New York: Proceedings of the 2012 International Symposium on Software Testing and Analysis,2012:133-143.

[6] Eric Bosman,Asia Slowinska,Herbert Bos. Minemu: the world’s fastest taint tracker[C]//Berlin,Heidelberg: Proceedings of the 14th international conference on Recent Advances in Intrusion Detection,2011:1-20.

[7] BeatriX,Igor Gutnik,JCie. BeaEngine: disassembler library x86 x86-x64[EB/OL]. (2010-1-6)[2014-1-3]http://beaengine.org.

[8] Alexander Sotirov. Heap Feng Shui in JavaScript[C]//Las Vegas: BlackHat USA,2007.

[9] Vasileios P Kemerlis,Georigios Portokalidis,Kangkook Jee,et al. libdft: Pratical Dydnamic Data Flow Tracking for Commodity Systems[C]//London: Preceedings of the 8th ACM SIGPLAN/SIGOPS International Conference on Virtual Execution Environment,2012:121-132.

[10] James Clause,Wanchun Li,Alessandro Orso. Dytan: a generic dynamic taint analysis framework[C]//New York: Proceedings of the 2007 international symposium on Software testing and analysis,2007:196-206.

[11] David (Yu) Zhu,Jaeyeon Jung,Dawn Song,et al. TaintEraser: protecting sensitice data leaks using application-level taint tracking[C]//New York: Newsletter ACM SIGOPS Operating Systems Review,2011:142-154.

[12] Milena,Vujosevic Janicic,Victor Kuncak. Development and evaluation of LAV: an SMT-based error finding platform[C]//Berlin,Heidelberg: Proceedings of the 4th intenational conference on Verified Software: theories,tools,experiments,2012:98-113.

[13] 猪儿虫小次郎(新浪微博网名).微软最近干了些啥[EB/OL].[2014-7-16]http://t.cn/RP7Wimy.

[14] Neuromancer. SEA: Symbolic Execution Assistant[EB/OL]. (2013-6-20)[2013-9-27]https://github.com/neuromancer/SEA.

[15] Feist J,Mounier L,Potet M L. Statically Detecting Use After Free on Binary Code[J].Journal of Computer Virology and Hacking Techniques,2014,10(3):1-7.

USE-AFTER-FREE VULNERABILITIES DETECTION SCHEME BASED ON S2E

Feng Zhen Nie Sen Wang Yijun Xue Zhi

(SchoolofInformationSecurityEngineering,ShanghaiJiaoTongUniversity,Shanghai200240,China)

Use-After-Free vulnerabilities are caused by the attempt of a program to operate on a dangling pointer. This type of vulnerability is growing rapidly in popularity,especially for exploiting web browsers. In this paper we propose a new algorithm to detect Use-After-Free vulnerabilities and implement the detection scheme UAFChecker accordingly. UAFChecker is based on S2E,an open source platform for in-vivo multi-path analysis of software systems. It monitors the creation of pointers by hooking key heap-operating functions and tracks the propagation of all pointers by using BeaEngine on assembly code level. Then it detects vulnerabilities by collection and analysis of information of pointers. Experimental result indicates that by collaborating with Fuzzing technology,UAFChecker succeeds in locating and analysing multiple 0-day Use-After-Free vulnerabilities in IE8 browser.

Use-after-free vulnerability Vulnerability detection Dangling pointer Taint propagation Symbolic execution

2014-08-26。国家自然科学基金项目(61332010);高级XXX技术研究(秘密级)(CNITSEC-KY-2013-009/2)。冯震,硕士生,主研领域:信息安全。聂森,博士生。王轶骏,讲师。薛质,教授。

TP3

A

10.3969/j.issn.1000-386x.2016.04.064

猜你喜欢

指针插件漏洞
漏洞
自编插件完善App Inventor与乐高机器人通信
为什么表的指针都按照顺时针方向转动
基于jQUerY的自定义插件开发
三明:“两票制”堵住加价漏洞
漏洞在哪儿
MapWindowGIS插件机制及应用
高铁急救应补齐三漏洞
基于改进Hough变换和BP网络的指针仪表识别
基于Revit MEP的插件制作探讨