0x00
本文是本系列的第三篇。本文将会介绍动态漏洞挖掘技术,本文的组织结构如下,首先介绍相关典型技术,如模糊测试、符号执行等并给出典型工具介绍,然后介绍相关技术存在的问题,如路径爆炸等,之后会用近期的顶会论文举例来了解的最新的学术界研究动态。
0x01
1.1模糊测试
模糊测试是一种基于缺陷注入的自动软件测试技术,它使用大量半有效的数据作为应用程序的输入,以程序是否出现异常作为标志,来发现应用程序中可能存在的安全漏洞。所谓半有效的数据是指对应用程序来说,测试用例的必要标识部分和大部分数据是有效的,这样待测程序就会认为这是一个有效的数据,但同时该数据的其他部分是无效的.这样,应用程序就有可能发生错误,这种错误可能导致应用程序的崩溃或者触发相应的安全漏洞
模糊测试是一个自动或半自动的过程,这个过程包括反复操纵目标软件并为其提供处理数据.模糊测试中的关键是模糊测试用例的生成方法,用于生成模糊数据的工具可称为模糊器.模糊器可分为两大类:基于变异的模糊器和基于生成的模糊器.前者对已有数据样本应用变异技术创建新的测试用例;后者通过对目标协议或文件格式建模的方法从头开始产生测试用例。
一般Fuzzing工具中,都会综合使用这两种生成方式。基于变异的算法核心要求是学习已有的数据模型,基于已有数据及对数据的分析,再生成随机数据做为测试用例
近年来最火的Fuzzing工具莫过于AFL。
AFL(American Fuzzy Lop)是由安全研究员Michał Zalewski(@lcamtuf)开发的一款基于覆盖引导(Coverage-guided)的模糊测试工具,它通过记录输入样本的代码覆盖率,从而调整输入样本以提高覆盖率,增加发现漏洞的概率。
①从源码编译程序时进行插桩,以记录代码覆盖率(Code Coverage); ②选择一些输入文件,作为初始测试集加入输入队列(queue); ③将队列中的文件按一定的策略进行“突变”; ④如果经过变异文件更新了覆盖范围,则将其保留添加到队列中; ⑤上述过程会一直循环进行,期间触发了crash的文件会被记录下来。
1.2符号执行
符号执行是一种用符号值代替数字值执行程序的技术,符号是表示一个取值集合的记号。使用符号执行分析程序时,对于某个表示程序输入的变量,通常使用一个符号表示它的取值,这个符号可以表示程序在此处接收的所有可能的输入。此外,在符号执行的分析过程中那些不易或者无法确定取值的变量也常常使用符号表示的方式进行分析。
符号执行的分析过程大致如下:首先将程序中的一些需要关注但是又不能直接确定其取值的变量用符号表示其取值,然后通过逐步分析程序可能的执行流程,将程序中变量的取值表示为符号和常量的计算表达式。程序的正常执行和符号执行的主要去呗是:正常执行时程序中的变量可以看做被赋予了具体的值,而符号执行时,变量的值既可以是具体的值也可以是符号和常量的运算表达式。
以下图的符号执行源代码为例,函数中的参数x,y分别用符号a,b表示
基于上图的代码可以得到下图所示的程序流程图
可以看到共有三条执行路径,每条路径都对应着一个路径约束(path constrain,PC)。其中返回true的路径有一条,带入符号后,对应的路径约束为a>60&(b2)==128;返回false的路径有两条,对应的路径约束为a<=60|(a>60&(b2)!=128)
这个例子表明,使用符号执行技术分析程序,对于分析过程中遇到的程序中带有条件的控制转移语句(条件分支语句、循环语句等),可以利用变量的符号表达式将控制转移语句中的条件转化为对符号取值的约束,通过分析约束是否可以满足,判断程序的哪条路径是可行的。这一部分是符号执行分析的关键部分。由此将判断路径条件是否可满足的问题转化为判断符号取值的约束是否可满足的问题。而对于约束是否可满足的判断,通常使用约束求解的方法,该过程由约束求解器完成(约束求解器是对特定形式的约束表示进行求解的工具)。在符号执行的分析过程中,常使用可满足性模理论(satisfiabilti modulo therries,SMT)求解器对约束进行求解,为此需要将符号取值约束的求解问题转为SMT问题,即一阶逻辑的可满足性判断问题。
Angr应该是目前最流行的符号执行工具。
它一个二进制代码分析工具,能够自动化完成二进制文件的分析,并找出漏洞。它基于python的二进制漏洞分析框架,将以前多种分析技术集成进来,它能够进行动态的符号执行分析(如,KLEE和Mayhem),也能够进行多种静态分析。
Angr主要架构如下
CLE模块:二进制的装载组建是CLE(CLE Load Everything),它负责装载二进制对象以及它所依赖的库,将自身无法执行的操作转移给angr的其它组件,最后生成地址空间,表示该程序已加载并可以准备运行。
ArchInfo模块:archinfo是包含特定于体系结构的信息的类的集合
PyVex模块:angr需要处理不同的架构,所以它选择一种中间语言来进行它的分析,angr使用Valgrind的中间语言——VEX来完成这方面的内容。VEX中间语言抽象了几种不同架构间的区别,允许在他们之上进行统一的分析
SimuVEX模块:中间语言VEX执行的模拟器
Clarity:这个模块主要专注于将变量符号化,生成约束式并求解约束式,这也是符号执行的核心所在,在angr中主要是利用微软提供的z3库去解约束式
angr及以上:是为上层封装好的接口
1.3污点分析
污点分析是一种跟踪并分析污点信息在程序中流动的技术,其分析对象是污点信息流。污点指的是受到污染的信息。在程序分析中,将来自程序之外并且进入程序的信息当做污点信息,。根据分析的需要,程序内部使用的数据也可作为污点信息,并分析其对应的信息的流向。根据污点分析时是否运行程序,可以将其分为静态污点分析和动态污点分析。
污点分析的过程包括:识别污点信息在程序中的产生点并对污点信息进行标记;利用特定的规则跟踪分析污点信息在程序中的传播过程;在一些关键的程序点检查关键的操作是否会受到污点信息的影响。污点信息的产生点称为source点,污点信息的检查点称为sink点。
以下图为例来说明污点分析过程
将scanf所在的程序点作为source点,将通过scanf接收的用户输入数据标记为污点信息,并且认为存放它的变量x是被污染的。如果在污点传播规则中规定“如果二元操作的操作数是污染的,那么二元操作的结果也是污染的”,则对于y=x+k,由于x是污染的,因此y也被认为是污染的。一个被污染的变量如果被赋值为一个常数,它将被认为是未污染的。对于x=0,将x从污染状态转变为未污染。对于while(i
1.3.1
识别污点源和污点汇聚点是污点分析的前提.目前, 在不同的应用程序中识别污点源和汇聚点的方法各不相同.缺乏通用方法的原因一方面来自系统模型、编程语言之间的差异.另一方面, 污点分析关注的安全漏洞类型不同, 也会导致对污点源和污点汇聚点的收集方法迥异.下图所示为在Web应用程序漏洞检测中的污点源示例, 它们是Web框架中关键对象的属性.
1.3.2
污点传播分析就是分析污点标记数据在程序中的传播途径.按照分析过程中关注的程序依赖关系的不同, 可以将污点传播分析分为显式流分析和隐式流分析.
污点传播分析中的显式流分析就是分析污点标记如何随程序中变量之间的数据依赖关系传播.下图所示的程序为例, 变量a和b被预定义的污点源函数source标记为污点源.假设a和b被赋予的污点标记分别为taint_a和taint_b.由于第5行的变量x直接数据依赖于变量a, 第6行的变量y直接数据依赖于变量b, 显式流分析会分别将污点标记taint_a和taint_b传播给第5行的变量x和第6行的变量y.又由于x和y分别可以到达第7行和第8行的污点汇聚点 (用预定义的污点汇聚点函数sink标识),下图代码存在信息泄露问题
污点传播分析中的隐式流分析是分析污点标记如何随程序中变量之间的控制依赖关系传播, 也就是分析污点标记如何从条件指令传播到其所控制的语句.在下图所示的程序中, 变量X是被污点标记的字符串类型变量, 变量Y和变量X之间并没有直接或间接的数据依赖关系 (显式流关系), 但X上的污点标记可以经过控制依赖隐式地传播到Y.具体来说, 由第4行的循环条件控制的外层循环顺序地取出X中的每一个字符, 转化成整型后赋给变量x, 再由第7行的循环条件控制的内层循环以累加的方式将x的值赋给y, 最后由外层循环将y逐一传给Y.最终, 第12行的Y值和X值相同, 程序存在信息泄漏问题
1.3.3
污点数据在传播的过程中可能会经过无害处理模块, 无害处理模块是指污点数据经过该模块的处理后, 数据本身不再携带敏感信息或者针对该数据的操作不会再对系统产生危害.换言之, 带污点标记的数据在经过无害处理模块后, 污点标记可以被移除.正确地使用无害处理可以降低系统中污点标记的数量, 提高污点分析的效率, 并且避免由于污点扩散导致的分析结果不精确的问题
0x02
前一部分我们分别介绍了三种典型的动态漏洞挖掘技术,这一节我们来看看它们分别存在哪些可以进一步研究的方向以及存在的缺陷。
2.1
通过模糊测试技术挖掘的漏洞仍大多是传统的堆溢出、栈溢出等溢出类漏洞,对于后门、验证绕过、多阶段触发等类型的漏洞却无能为力。更重要的是模糊测试并不能保证覆盖到所有的语句分枝,目前模糊测试的自动化程度还不高。如何克服缺陷、提高模糊测试的效率是模糊测试未来研究的热点。模糊测试未来研究的热点可能包括以下几个方面。
2.1.1
提高模糊测试的自动化程度。
模糊测试的主要问题在于它是一种盲注入的方式,手工进行模糊测试工作量过大,甚至几乎无法进行比较全面的测试,导致其实用价值受到很大影响,在常用的模糊测试框架中,目标软件的漏洞成因、目标软件的输人数据的规约、生成测试用例等往往需要人工参与。目前大量的关注点在于研究自动化与智能化的模糊测试方法。
2.1.2
优化测试用例生成策略。
模糊测试中关键的步骤是测试用例生成,传统的模糊测试在生成测试用例时往往盲目地去变异正常测试用例中某一部分,会造成测试用例规模可能达到百万级别,但其测试效果并不理想。因此,测试用例生成策略的设计与改进是目前模糊测试技术的热点研究内容之一。
引入退火遗传算法等对测试规则进行改进,使得最小测试用例集合能够覆盖最大的代码执行路径 以发掘那些隐藏较深的软件漏洞,是目前模糊测试技术的发展趋势。
2.1.3
与虚拟机技术相结合。
与虚拟机技术相结合,能够快速、全面地获取不安全函数、目标程序的更多反馈信息,进而生成畸形度更高、正确度更高的测试数据来改善漏洞挖掘的效果
2.1.4
模糊测试效果的评估技术研究
以SAGE为代表的模糊测试框架以代码覆盖率来评价模糊测试效果,测试的过程缺乏聚焦性,测试路径通常会随意扩散,这往往是不直接、不科学的.
从不安全代码的覆盖率、程序状态的覆盖率、输入边界测试的充分性、缓冲区边界覆盖的充分性、测试数据的有效性和知识获取的充分性等多个角度来衡量测试效果会更加科学,也能更好地指导测试用例的生成和模糊测试技术的进一步发展.
2.2
符号执行主要存在两个问题:路径爆炸和约束求解。
2.2.1
路径爆炸问题是制约符号执行在现实程序分析中应用的主要因素.因为在符号执行的分析过程中,在每个分支节点,符号执行都会衍生出两个符号执行实例,程序分支路径的数量与程序分支的数量呈指数级增长关系.以下图中的代码为例,代码中共有3个分支判断语句和1个循环语句,3个分支判断语句根据x,y,z值的不同,将会产生8条不同的程序路径;而对于循环来说,当a取最大值时,该循环将会产生2的31次方条路径。
一种对应的解决办法称为状态合并。
状态合并能极大地缩减程序的状态空间,从而减小路径空间,如下图所示,其将2^n条路径缩
为1条,效果十分显著.但是,状态合并需要满足合并不能造成副作用的条件,即进行状态合并不影响程序分析的准确性,这是状态合并的关键也是其难点所在
2.2
约束求解的限制仍然是提高符号执行引擎可用性的主要障碍.约束求解的核心问题是将路径条件的算术约束条件转换为基本的求解器问题,其难点主要是:1)非线性整数约束往往使得路径条件不可解,带有非线性约束的约束集一般是不可判定其可解性的;2)对于路径约束条件中包含的外部库函数调用的情况,求解器也无法进行处理。
相关研究人员也提出了针对约束求解的优化方法,其中两个突出的优化思想是:无关约束消除技术和缓存求解策略
1)无关约束消除的目的是要通过分析来减少约束项的数量.一个重要的事实是,一个程序分支通常只依赖于一小部分程序变量,该分支所依赖的程序变量可能与该路径上其他约束包含的变量相互独立.因此,可以尝试从当前路径约束中识别出与当前分支结果不相关的约束并移除。
2)缓存求解策略能提高约束求解性能的根据是,在进行程序分析测试过程中,经常会涉及到相似约束集的求解,尤其是与约束独立性判定方法结合使用时,缓存求解策略显得更为有效.例如:在混合测试中,求解新路径的方法是将当前执行路径中的某个分支条件进行约束取反,得到新的约束集后再进行求解,所得结果即为新路径的测试用例.在这种情况下,如果缓存了先前执行中约束公式及其解的匹配,就可以很快地借助先前的解来求解新的约束集.假设缓存中包含一个匹配:formula:(x+y<10)∩(x>5)→solution:{x=6,y=3},而在后续的分析中遇到一个新的约束集为缓存匹配中某约束集的子集,则可以直接将缓存中该约束集对应的solution作为新遇到的约束集的解.另外,若后续分析中遇到的约束集是缓存中约束集的超集,如(x+y<10)∩(x>5)∩(y≥0),则无法确定之前缓存中的结果是否可以直接使用,因此可以尝试借助先前缓存中的solution来判断其是否为可行解
2.3
污点分析技术有很多问题并没有得到完全解决。
一是现有工具仅基于某一层次进行污点分析。比如基于应用程序的污点分析虽然可以检测程序运行中存在的隐私数据泄露问题,但隐私数据在数据库或系统进程中同样存在泄露隐患。污点分析精度与效率之间的矛盾不可调和。动态污点分析是在原系统基础上扩展了污点跟踪机制,需要占用系统资源,导致系统效率下降,分析精度要求越高,需要获得的污点分析数据就要越详细,系统效率下降就越严重,需要在精度与效率之间进行平衡。
污点分析技术未来研究的出发点就是如何提高污点分析技术的性能。总的来说,主要包括以下两个方面
2.3.1优化污点分析技术方法
可以通过设计更科学的污点识别方法、归纳更准确的污点传播策略以及引入新算法等方法来提高污点分析技术的准确性和分析效率。
为了提高污点数据识别的精度,有研究者引入机器学习的概念来识别污点源和污点汇聚点,如Tripp等使用Bayesian模型对污点源进行分类,从中排除正常的数据发送请求,降低了对污点分析造成的影响
从制定更科学的污点传播策略出发,有研究者提出基于执行踪迹离线索引的方法,在污点分析过程中,筛选出与污点数据相关的操作的同时忽略与污点数据无关的指令,从而缩短污点分析时间。
也可以考虑引入新算法提高污点分析性能。一方面可以将污点分析问题转换为其他问题,如:静态污点分析框架Parfait,在程序预处理阶段将污点分析问题转换为图可达性问题,实现了针对C代码的静态污点分析;另一方面可以采用并行处理技术进行污点分析,提高污点分析执行速度,如:动态污点分析框架DTAM可并行执行多个线程单元的污点分析,再将分析结果进行聚合,提高了对可并行执行的多线程程序进行动态污点分析的效率。
2.3.2结合其他研究方法
为提高污点分析技术的精度和效率,还有研究者将不同的技术方法结合使用,以综合各方法的优点,主要介绍以下两种方法
一种是与符号执行结合。将污点分析与符号执行结合使用的分析工具有Angr和DsVD等。
有研究者提出了基于类型的动态污点分析技术,其核心思想是将类型信息和符号值作为污点信息,在程序执行时同时进行动态污点分析和符号执行,程序运行结束后获得污点传播信息和程序执行路径条件,最后通过求解得到输入变量满足的約束条件。这种技术结合了动态污点分析和符号执行的优点,对程序有较为全面的理解。
另一种是与模糊测试结合。我们知道模糊测试的缺点之一是对程序漏洞作用机理缺乏基本的理解。为了解决这个问题,研究者提出了定向模糊测试方法,将模糊测试和污点分析相结合,在异常测试样本集的基础上进行污点分析,深入了解漏洞作用机理,并在此基础上实现了SmartDroid、Brahmastra等工具。
0x03
在这一部分,限于篇幅,介绍一篇近期的顶会论文的工作。
论文名为《Fuzzing Error Handling Code Using Context-Sensitive Software Fault Injection》,发表于USENIX Security 2020。
3.1
背景是这样的:异常处理代码中可能存在漏洞,这些漏洞可能造成DOS、信息泄露等安全隐患。而目前的fuzzing方式很难覆盖到这些代码,因为这些异常处理代码只在某些错误发生时被调用(内存、网络、文件)。
针对异常处理代码的传统测试方式为software fault injection(SFI),SFI通过向程序中引入异常,来测试程序是否能够正常处理异常。而目前的SFI技术只能进行context-insensitive的fault injection,存在较大的局限性。如下图所示,context-insensitive的SFI会将两个malloc都引入异常,因此无法触发bug。
作者提出了一种基于context-sensitive SFI的fuzzing方式,能够有效的发现异常处理代码中的bug。
3.2
所实现的FIFUZZ由六个部分组成:Error site extractor、Program generator、Runtime monitor、Error-sequence generator、Input generator、Bug checkers
•Error site extractor。对测试程序的源代码执行自动的静态分析,以识别可能的error site。
•Program generator。对程序代码执行代码检测,包括已识别的错误位置,功能调用,函数入口和出口,代码分支等。它生成可执行的经过测试的程序。
•Runtime monitor。使用生成的输入来运行测试的程序,收集测试程序的运行时信息,并根据生成的错误序列执行故障注入。
•Error-sequence generator。根据收集的运行时信息创建错误序列,并对错误序列进行突变以生成新的错误序列。
•Input generator。根据收集到的运行时信息执行传统的模糊处理以变异并生成新的输入。
•Bug checkers。检查收集的运行时信息以检测错误并生成错误报告
3.4作者使用AFL、AFLFast、AFLSmart、FairFuzz与FIFUZZ对五个旧版本程序进行测试,结果如下:
图13绘制了模糊测试期间每个测试程序的覆盖代码分支。与AFL和AFLFast相比,FIFUZZ通过覆盖更多的错误处理代码,在所有经过测试的程序中覆盖了更多的代码分支。与AFLSmart和FairFuzz相比,FIFUZZ在nm,size,ar中涵盖了更多的代码分支,但在objdump,readelf中涵盖了更少的代码分支。主要原因是FIFUZZ中程序输入的模糊处理是通过引用AFL来实现的,而AFLSmart和FairFuzz使用一些技术来改进AFU的模糊输入的突变和种子选择。出于这个原因,尽管AFLSmart和FairFuzz仍然错过了FIFUZZ覆盖的许多错误处理代码,但它们可以覆盖与输入有关的不经常执行的代码。如果在FIFUZZ中实现程序输入的模糊处理,则与所有测试的程序相比,AFLSmart和FairFuzz可以覆盖更多的代码分支。
表9显示了错误检测的结果。首先,AFL和AFLFast发现的两个漏洞也被AFLSmart,FairFuzz和FIFUZZ发现。其次,AFLSmart和FairFuzz分别找到了AFL,AFLFast和FIFUZZ遗漏的一个漏洞.AFLSmart发现的一个额外漏洞与FairFuzz发现的不同,因为它们以不同的方式改善了程序输入的变异和种子选择。最后,FIFUZZ发现了14个漏洞,其中12个与错误处理代码有关,AFL,AFLFast,AFLSmart和FairFuzz均未找到。
3.5
总结一下,作者的贡献在于:
1)针对于异常处理代码进行了调研,发现42%的异常处理代码与偶尔发生的异常相关联;而现有的fuzzing工具仅能发现少量与异常处理相关的漏洞。
2)提出了一个种基于context-sensitive的SFI fuzzing方式,能够动态的根据异常处理代码的上下文注入错误,以覆盖那些传统fuzzer难以触发的异常处理代码。
3)基于该方法实现了一个fuzzing framework,FIFUZZ,能够高效的测试异常处理代码。FIFUZZ时第一个能够基于函数上下文来测试异常处理代码的fuzzing framework。
4)对FIFUZZ在9个被广泛应用的C语言程序上进行测试,发现了50个漏洞。并与现有的fuzzing工具进行对比,发现了他们无法找到的漏洞。
0x04
参考文献如下:
1.http://blog.amossys.fr/intro-to-use-after-free-detection.html
2.https://www.cnblogs.com/0xJDchen/p/9291335.html
3.https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8805076
4.http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=7401
5.http://jifeng-xuan.com/page/paper/jos_19.pdf
6.https://angr.io/
7.lcamtuf.coredump.cx/afl/
8.http://www.jos.org.cn/html/2017/4/5190.htm
9.http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=224
10.http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=16032
11.《从自动化到智能化:软件漏洞挖掘技术进展》
12.http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=224
13.http://www.jos.org.cn/html/2017/4/5190.htm
14.http://www.fx361.com/page/2019/1023/5882383.shtml
15.《Fuzzing Error Handling Code Using Context-Sensitive Software Fault Injection》
16.《污点分析技术研究综述》
17.https://securitygossip.com/blog/2020/07/15/fuzzing-error-handling-code-using-context-sensitive-software-fault-injection/
18.https://www.usenix.org/system/files/sec20fall_jiang_prepub.pdf