方浩然
等
使用活跃轨迹高效挖掘污点风格漏洞
溃(Crash)来发现缺陷和安全漏洞.对于非崩溃漏洞如数组越界、内存未初始化、数据竞争等, Sanitizers
[2-4]
系列动态分析工具(如 MSan/TSan/ASan)通过编译期插桩,能够在运行时让这些更隐蔽的漏洞暴露出来,因此常
常被 Fuzzing 工具集成以提高其发现漏洞的能力.
DFSan
[2]
是 Sanitizers 系列中的动态污点分析工具(DTA).污点分析
[5]
是一种经典的程序安全分析方法,能够
发现如 SQL 注入、隐私泄露等非 Crash 漏洞,我们称之为污点风格的漏洞(Taint-Style Vulnerability).如果不可信
的外部输入(Source 引入的污点数据)未经验证(Validate)或消毒(Sanitize),通过数据/控制依赖传播,流入敏感操
作(Sink),说明存在污点传播路径,从而产生潜在的信息流安全问题.造成心脏滴血漏洞
[6]
的缓冲区溢出就可以
被视为污点风格漏洞.如同其他程序分析技术,静态和动态污点分析存在其固有局限性.静态分析通常是可靠
(Sound)的,但由于路径不敏感性(如经典的不动点迭代式数据流分析)、缺少运行时信息等因素产生误报;动态分
析依赖于测试集的完备性,只能分析执行的程序路径,因而产生漏报.
Fuzzing通过变异或语法模板大量生成测试用例,可以用于验证静态分析结果,消除误报和降低漏报.然而我
们发现,如果将现有Fuzzer如AFL直接用于Source-Sink之间的污点传播路径搜索时,有效性和准确性都有待提
高.现有CGF广泛采用边覆盖反馈机制,多数漏洞被视为存在于某个分支下的特殊代码,当特定的输入探索到此
分支时,漏洞就会被触发.然而对于污点风格漏洞,是否触发与到达漏洞点的路径强相关,我们称之为路径敏感.
一对Source和Sink
之间通常存在多条路径,可能只有其中少数几条能够传播污点到Sink,并且由于污点清洁函数
Sanitizer的存在,使得这种精确的路径搜索十分困难.边覆盖作为信息反馈在面对此类漏洞时过于粗糙: 大量与
污点传播无关的种子被加入队列,对这些种子做Fuzzing是低效的;当高频的边覆盖完成后,后续测试用例在
Source-Sink之间产生的新路径无法被识别,这使得队列中与污点传播相关的种子数量又过早收敛,不能过滤出
真正执行污点传播的好种子,从而导致Fuzzing失去进化方向,无法系统高效地搜索污点传播路径.定向Fuzzer通
过优化种子选择和能量调度策略使Fuzzing朝着特定的目标进行,但很多实现基于AFLGO从而继承AFL的边覆
盖反馈机制,仍然存在上述问题.正如Neutaint
[42]
中所说,“不论任何形式的DTA,找到一条新的污点传播路径都
是一个困难的问题”.
本文提出了一种高效的 Fuzzing 方法挖掘污点风格漏洞,并实现原型系统 TaintPoint.该方法的关键是去除
覆盖反馈信息中的噪音,过滤出污点传播问题上真正的好种子.边覆盖产生的轨迹是一种无差别的控制流信
息,TaintPoint 在控制流的基础上,加入活跃污点这种问题相关的数据流信息,只记录存在活跃污点信息的有效
执行轨迹,形成活跃轨迹(Live Trace)作为反馈信号,并且围绕活跃轨迹在插桩、种子过滤和选择、变异阶段分
别改进现有 Fuzzing 方法.
首先, TaintPoint 通过静态分析识别出 Source-Sink 相关的潜在危险区域.基于系统依赖图 SDG
[7]
,我们实现
了一个静态 Chopper 组件,识别出与 Source-Sink 依赖相关的基本块.与标准后向切片(Backward Slicing)不同的
是, Chopper 在 SDG 上进行两次可达性分析.根据指定的 Source 和 Sink 点,分别进行正向和反向切片,取其交集
基本块并做危险标记,表明从 Source 引入的污点数据将沿着这些潜在的危险基本块到达 Sink.在插桩阶段,我们
将这些危险基本块之间形成的轨迹(Trace)在单独的共享内存中进行标记.分离式插桩区分出了两类轨迹,同时
在危险基本块之间形成逻辑边,从而减弱无关部分对污点传播路径搜索的影响.
Source-Sink 之间存在的消毒函数(Sanitizer)会截断污点传播,受影响的变量不再带有污点属性.若在某个程
序分支点,所有处于后续危险基本块中的活跃变量都是未被污染的,则说明在此程序点以后不会存在污点传播
路径到达 Sink. TaintPoint 进行活跃变量分析,在危险标记的每个分支基本块出口处插桩,以获取运行时的活跃
污点信息.若某个分支处的有效活跃变量都没有被污染,则不记录此分支点及以后的轨迹,只记录有活跃污点传
播的活跃轨迹(Live Trace).
在种子过滤阶段,如果测试用例在危险区域产生了新的覆盖,那么加入队列的同时给予该种子特殊标记以
提升其优先级.部分种子因为中途离开危险区域或被消毒而中断了 Live Trace 的记录,若存在新的种子重新回
到危险路径上或者绕过了消毒函数,产生的活跃轨迹是前者的超集,该种子对于污点传播问题来说是一个更好
的种子.在种子选择阶段,TaintPoint 提出了新的进化方向,优先选择活跃轨迹更长的种子去变异. Fuzzing 将沿着
评论