基本信息
原文名称 COOPER: Testing the Binding Code of Scripting Languages with Cooperative Mutation
原文作者 Peng Xu;Yanhao Wang;Hong Hu;Purui Su;
原文链接https://www.ndss-symposium.org/
wp-content/uploads/2022-353-paper.pdf
发表期刊 Network and Distributed Systems Security (NDSS) Symposium 2022
开源代码 https://github.com/TCA-ISCAS/Cooper
一、 引言
像JavaScript这样的脚本语言正在被集成到商业软件中,以支持轻松的文件修改。例如,Adobe Acrobat接受JavaScript来动态操作PDF文件。为了弥合高级脚本和用于实现软件的低级语言(如C/C++)之间的差距,需要一个绑定层来传输数据和转换表示等工作。然而,由于双方的复杂性,绑定代码容易出现安全漏洞以及语义不一致的情况,从而严重影响软件的安全使用。现有的绑定代码测试工作只集中在脚本端,因此错过了需要特殊文本内容输入所触发的错误。例如,favocato[1]只是修改JavaScript语句,以触发绑定层中的错误。为解决这一限制,应从两个维度对输入进行变异:修改文件内容以影响程序的初始状态,以及合成有效脚本以触发更多样的状态。然而,由于变异空间大,随机变异的简单方法无法有效地探索绑定代码。原生文件输入包含许多对象,但并非所有对象都与绑定代码相关,而脚本代码只接受特定的程序状态进行进一步操作。
因此,针对于上述问题,作者提出了COOPER,使用统计方法关联文件输入和脚本进行协同变异,在如下两方面做出了创新:
(1)为提高相关模糊测试的覆盖程度,本文设计从文件原生内容和脚本代码两个维度对种子文件进行变异;
(2)为提高变异的效率,本文设计了推断文件原生内容输入和脚本代码之间关系的模型,并利用这种关系来指导二维突变。
二、 概述
Cooper的基本框架如下图所示,主要由三部分组成:
(1)对象聚类:PDF文件被组织为对象树。每个对象都有一个唯一的标识符,其内容在一对关键字obj和endobj中定义。此外,Word文档也可以转化为XML,这种结构化文档也可以看作由一个个对象构成。所以一开始,Cooper解析给定的示例文档以提取本地文件对象。为了减少对象搜索空间,Cooper根据对象的属性将其分类为不同的类。
(2)关系推断:然后,Cooper推断对象类和脚本Api组之间的关系。具体来说,它通过组合不同的对象类和API组来生成大量文档,并记录嵌入脚本的执行结果。基于脚本执行的成功率和对象类的分布,Cooper推断了Api组和对象类之间的关系。
(3)关系引导的变异:最后,Cooper利用推断的关系来指导对象选择、脚本生成和对象变异。本文还设计了几种合作突变策略。
图1 Cooper流程概述图
三、对象聚类
1)Clustering Value Objects:根据本文作者的实验,大多数文件对象都被用作其他对象某个属性的值,而在属性名中通常包含着高级语义信息,这使得如果两个对象可以用作同一属性的值,那么它们将具有相似的特性。因此,在第一步中,本文作者使用属性名称对其值对象进行聚类。具体来说,作者将检查每个属性的(name,object)对:如果找到一个新的属性名称,将创建一个新的类,并将对象放入该类中;如果是已发现的属性名称,则将对象放在该类中。对于不用作值的对象,只需将它们放入一个特殊的类中。该过程如图2所示。
图2 Clustering Value Objects示意图
2)Clustering with Attribute Similarity:为了对第一步处理过的类进行更精细的划分,作者使用Dice系数来衡量对象的相似性,完成现有类的拆分和合并。具体过程如公式1所示,A和B是两个对象的属性集,|A|是A中的属性数量,而|B|是B中的属数量, 为共有属性的数量。如果sim(A,B)大于阈值θ(文章中设θ=0.7),则把它们合并为一类,如果sim(A,B)小于0.3则把它们分成两类。为了简化类之间的计算,文章作者决定使用高频属性(类中至少有一半的对象拥有的属性)来代表类中的所有对象。
四、关系推断
1)Interface Recognition:本文作者手动分析了有关软件在所支持的脚本语言方面的官方手册,特别是接口定义和API引用,以识别可以访问文档中定义的内容对象的API。此外,还采用了favocado[1]中提出的方法,根据API的高级语义对其进行聚类,并构建了用于脚本代码生成的模板语料库。
2)Execution Logging:本文所实现的系统可以自动将生成的脚本插入到每个文档中。通过被测试的应用程序打开每个修改后的文档,并记录嵌入脚本的执行结果。为了记录执行结果,脚本必须包含两个日志操作。首先,在一次调用任何API之后,本文将使用适当的语句来保存返回值,例如通过打印函数或保存到日志文件。成功调用表示文档包含当前API执行所需的对象。其次,为了记录引发异常的意外错误,本文插入故障处理代码来挂接异常并记录错误消息。此步骤生成一组形式为(document,API,result)的元组,其中document标识测试文件,API表示相关的API,result表示执行结果。
3)Relationship Inference:用于推断的算法如图3所示,首先,对于每个API f,先找到所有相关的执行结果,包括成功(表示为Sf)和失败(表示为Ff)。然后,对于每个对象类c,找到在类c中至少包含一个对象的所有文件(表示为IN)。接下来,计算所有包含c中的任何对象的成功文件在所有成功文件中的比例,表示为rateS;类似地,计算了所有失败文件中包含c中任何对象的文件的比率,表示为rateF。最终,采用rateS和rateF的差异表示每个API与每类对象的关联程度。
图3 关系推断算法
五、关系引导的变异
首先,选择一组API作为测试目标,本文作者采用类似于基于语法的模糊器domato[2]的方法来生成脚本代码,它将语言语法、语句格式、预定义模板和其他信息(如类型和值范围)作为输入,并创建使用所选API的脚本。接着,本文从RelationMap(关系推断的结果)中找到一组对象类进行变异。本文根据rate值来分配模糊能量,每类对象被选中变异的概率如图4中对象选择的公式所示,该公式定义了类别c被选择用于突变的概率,其中AP I包括所有选择的API,而i覆盖与这些AP I相关的所有类别。
图4 变异执行流程
本文设计了三种突变方法:
Attribute Mutation:该突变策略将修改对象的属性(即一个名称-值对)。首先,随机选择一个对象的一个属性,并将其替换为同一类中其他对象的另一个属性。大量的样本将为每一类对象提供不同的属性。其次,随机选择一个属性,并将其插入到同一类中的其他对象中。由于属性可以是可选的,因此插入操作可能会增加对象属性的数量。第三,从对象中删除可选属性以减少其属性。最后,将一个属性的值替换为其他属性的其他值。
Whole-object Mutation:除了属性突变外,本文还对整个对象进行了修改,以提高突变效率。当对象从未被用作值时,这一点尤为必要。整个对象突变还包括三个操作:对象替换、插入和删除。对于替换,随机选择同一类中的另一个对象来替换当前对象,应保留对象的标识符,以便所有对旧对象的引用现在都引用新对象。对于删除,随机选择一个对象,并用随机字节替换其内容。同时,找到所有对旧对象的引用,并将其替换为Null。对于插入,只将新元素添加到Array对象中,其中新对象来自现有对象的类。
Universal Mutation:如果一类对象在rateS和rateF中都有很高的值,本文作者将它们视为公共对象,相应地执行两个突变。首先,插入众所周知的易触发bug的值,以便触发边界条件。例如,对于整数,赋值器将它们替换整数的最大值和最小值;对于字符串,用Null对象替换它们,并在字符序列中随机插入0。其次,将修改特定对象的大小。对于字符串和数组,将它们的长度设置为零或一个非常大的值。在对象级别,可能执行删除其中的所有属性或将现有属性复制到最大数量。
六、 实验设计及结果
(一)具体实现
在系统实现过程中,作者修改了一个开源的PDF解析器——PyPDF2[3],将PDF文件解析为对象,并构建对象之间的相互引用图。对于DOCX文件,本文使用python库zipfile将文件解压缩为分层目录文件。然后,使用python库xml来修改文件结构。
在脚本生成方面,为了解决之前代码生成单行模板的单调问题,本文作者引入了由多行代码组成的块级模板,使本文实验所用的系统能够轻松地构建具有复杂循环和条件语句的代码。
(二)实验设置
本文实验将对 Adobe Acrobat,Foxit Reader和Microsoft Word进行模糊测试。为了检测本文提出的各种方法是否对真实环境中的模糊测试有所提升,作者设置了如图5的五个实验组用来对比效果。COOPER-full是功能齐全的COOPER。COOPER-random不使用基于关系的指导,而是随机选择和变异对象和API。COOPER-object只修改与绑定代码相关的对象,而COOPER-script只更改脚本,不更改任何对象。最后一个实验是使用现有的JavaScript模糊器Domato进行的,它用与COOPER脚本略有不同的方式修改JavaScript代码。由于Domato是为测试通用JavaScript代码而设计的,所以作者为其添加了JS模板以生成PDF文档相关JavaScript代码,并添加了VBA模板以生成DOCX文件。
图5 实验设置
(三)具体实验
实验一:分析对象聚类和关系推理是否合理
为了检测对象聚类和关系推理方法的合理性,作者手动检查了一些中间结果,以证明其见解和结果之间的一致性。其中,对12,374,420个PDF对象聚类过程最终形成了901个对象类,作者对其中的一些分类结果进行了手动分析,其结果符合本文所提出的理论。对于关系推断的分析,由于RelationMap将每个API映射到一组对象类,其中每个类都有与之相关的突变概率,因此作者检查了Acrobat和Foxit Reader中与Annotations对象相关的API,以检测推理算法的合理性。表1显示了对象类和API之间的推断细节,根据每个相关类的属性,作者手动搜索和分析PDF文档和JavaScript引用,以确认它们是否与Annotations相关。其中/AP,/Fm45,/Annots都为Annotations对象中常见的有效属性。最终,手动分析显示对象聚类和关系推理符合文章的预期。
表1 对象类和annotation APIS之间的关系
实验二:测试发现bug数量
为了验证COOPER组件在真实环境中的有效性,作者对Adobe Acrobat和Foxit Reader,进行了一周的实验(即168小时),图6显示了实验结果。经过一周的测试,COOPER-object最终报告了Adobe Acrobat中的4个未知错误和Foxit Reader中的3个未知错误,而COOPER-script确定了8个Adobe Acrobat中的未知错误和Foxit阅读器中的5个未知错误。与COOPER-full的结果(Acrobat有发现18个未知bug,Foxit有发现14个未知bug)相比,证明了二维突变的必要性。同时,具备关系指导变异模块的模糊测试工具比随机变异的表现更为突出。
图6 发现未知bug的数量
最终,作者利用COOPER在Adobe Acrobat、Foxit Reader和Microsoft Word三个商业软件中,检测到134个以前未知的漏洞,其中33个漏洞被分配了CVE编号。部分漏洞如表2所示。
表2 COOPER发现的未知漏洞
实验三:代码覆盖率测试
由于测试程序的封闭源代码性质,无法直接区分绑定代码和其他代码。为了解决这个问题,本文依靠脚本引擎和调用堆栈的公共接口来识别与绑定层相关的代码。具体来说,本文使用 Intel PIN[4](一种动态检测工具)运行每个程序,并为每个分支检查当前调用堆栈是否包含脚本引擎的公共接口。如果这样的接口(即Foxit的FXJSE_ExecuteScript、Acrobat的EScript.api模块中的任何函数、Word的VBE7.dll模块中的任意函数)在调用堆栈中,将分支视为与绑定层相关。否则,分支仅用于底层代码。实验结果如图6所示。
可以看到,COOPER-full在脚本代码和底层代码的覆盖率方面始终优于其他配置和工具。例如,在测试Adobe Acrobat时,与COOPER-random、COOPER-object、COOPER-scrip和Domato相比,COOPER-full在脚本代码上的边缘覆盖率分别提高了11.5%, 637.2%, 17.7% 和 13.0%。同时,与其他代码相比,它在底层代码上的边缘覆盖率分别提高了22.4%, 24.8%, 39.3%和 36.5%。这一结果表明,COOPER在测试采用绑定层的程序时可以提高代码覆盖率,同时,也可以解释为什么它可以检测到这么多严重的漏洞。
图7 不同配置的实验组的边覆盖情况
七、 总结
作者提出了合作变异,用于测试脚本语言绑定代码以发现内存安全问题。协同变异同时修改脚本代码和相关的文件内容输入,以探索绑定代码的各种代码路径。为了支持协同变异,本文对本地输入和脚本API之间的关系进行推断,并使用该关系来指导二维变异。此外,作者将COOPER应用于三种流行的商业软件,Adobe Acrobat、Foxit Reader和Microsoft Word检测到了134个以前未知的漏洞,其中33个被分配了CVE编号,并且获得了2.2万美元的漏洞奖励。
参考文献
1.
S. T. Dinh, H. Cho, K. Martin, A. Oest, K. Zeng, A. Kapravelos, G.-J.Ahn, T. Bao, R. Wang, A. Doupé et al. Favocado: Fuzzing the BindingCode of JavaScript Engines Using Semantically Correct Test Cases. Proceedings of the 28th Annual Network and Distributed System Security Symposium (NDSS), Virtual, Feb. 2021.
2.
I.Fratric. Domato: A DOM Fuzzer. https://github.com/googleprojectzero/domato, (accessed July 10, 2021).
3.
PyPDF2.PyPDF Documentation. https://pythonhosted.org/PyPDF2/,(accessed July 23, 2021).
4.
C.-K. Luk, R. Cohn, R. Muth, H. Patil, A. Klauser, G. Lowney, S. Wallace,V. J. Reddi, and K. Hazelwood. Pin: Building Customized Program Analysis Tools with Dynamic Instrumentation. Proceedings of the 2005 ACM SIGPLAN Conference on Programming Language Design and Implementation, 2005.