一种针对JavaScript引擎JIT编译器的模糊测试方法

第54卷 第1期2021年1月
通信技术
Communications Technology
Vol.54 No.1
Jan. 2021
文献引用格式:王越,孙亮,王轶骏,等. 一种针对JavaScript引擎JIT编译器的模糊测试方法[J].通信技术,2021,54(01):175-180.
WANG Yue, SUN Liang, WANG Yijun, et al. A Fuzzing Method for JIT Complier of JavaScript
Engine [J].Communications Technology,2021,54(01):175-180.
doi:10.3969/j.issn.1002-0802.2021.01.028
一种针对JavaScript引擎JIT编译器的模糊测试方法*
王 越1,孙 亮2,王轶骏1,薛 质1
苏南人力资源市场(1.上海交通大学 ,上海 200240;2.江苏省南通市公安局,江苏 南通 226001)
摘 要:JavaScript引擎的安全性是浏览器安全的重要一环,以往针对JavaScript引擎的模糊测试工具很难针对JIT编译器部分进行有效挖掘。对此提出了一种针对JIT编译器的模糊测试方法,使用基于中间语言的生成算法生成JIT种子文件,在保持该种子文件中间语言结构的情况下进行变异。
相比于其他模糊测试工具,本方法的测试样本有更高的模糊测试JIT编译器的成功率,并能达到更高的JIT编译器的覆盖率,从而表明该方法针对JIT编译器的模糊测试具有更好的性能优越性。
关键词:JavaScript引擎;JIT编译器;模糊测试;覆盖率
中图分类号:TP393.08 文献标识码:A 文章编号:1002-0802(2021)-01-0175-06
A Fuzzing Method for JIT Complier of JavaScript Engine
WANG Yue1, SUN Liang2, WANG Yijun1, XUE Zhi1
(1.Shanghai Jiaotong University, Shanghai 200240, China;
2.Nantong Public Security Bureau, Nantong Jiangsu 226001, China)
Abstract: The security of JavaScript engine is an important part of browser security. In the past, the fuzzing tools for JavaScript engine were difficult to effectively mine the JIT compiler part. In this regard, a fuzzing method for JIT compilers is proposed, which uses an intermediate language-based generation algorithm to generate JIT seed files, and mutates while maintaining the intermediate language structure of the seed files. Compared with other fuzzing tools, the testcases of this method have a higher success rate of fuzzing the JIT complier, and can reach a higher coverage rate of the JIT complier, which indicates that the method has better performance superiority for JIT compiler fuzz testing.
Keywords: JavaScript engine; JIT compiler; fuzzing; coverage
0 引 言
Web浏览器安全是用户在网络环境中至关重要的一环,而JavaScript引擎是浏览器中的重要组件,攻击者可以通过钓鱼网页轻易地让用户触发JavaScript引擎漏洞。JavaScript引擎又是内存危险的,触发漏洞后攻击者可以构造特殊的原语来实现内存的任意读写,从而控制被攻击者的设备。JavaScript引擎漏洞在近几年频繁出现,伴随的利用脚本都仅仅需要远程浏览器访问,范围覆盖Windows、MacOS、iOS、Android各种操作系统,故
* 收稿日期:2020-09-10;修回日期:2020-12-10 Received date:2020-09-10;Revised date:2020-12-10基金项目:国家重点研发计划项目“网络空间安全”重点专项(No. 2017YFB0803203)
Foundation Item: National Key Research and Development Program Project “Cyberspace Security” Key Special Project(No.2017YFB0803203)
通信技术
<2021年
JavaScript引擎的安全问题已经是安全研究的重点对象。
近几年来,JavaScript引擎漏洞中JIT编译器的漏洞占据了越来越大的比重。JIT编译器,全称(Just-In-Time)是一种程序语言提高运行效率的方法。如图1所示,JavaScript引擎解释执行JavaScript的流程为:先通过词法和语法分析将JavaScript脚本转化为AST树,然后编译为中间语言字节码,接着进行逐步解释执行,当执行的过程出现多次循环或者多次函数调用时,JIT编译器会将该部分字节码重新编译,通过编译优化提升运行效率,最终转化为符合操作系统的机器码并执行。
JavaScript
AST
字节码
需要优化
解释器JIT编译
机器码
否是
图1 解释执行JavaScript流程
JIT优化阶段,JIT会将优化拆分成为多个步骤(如常数折叠、循环不变量提升等),这些步骤即为每一个具体的JIT优化阶段。JIT优化时会将需要优化的代码进行分析,当其满足优化阶段的条件时,进行优化。
JIT编译器漏洞,主要包含的是JIT优化相关的漏洞,优化漏洞通常在JIT编译优化过程中利用错误预测或绕过检查而达到利用。其中包含绕过边界检查,如CVE-2015-0817、CVE-2017-2547和 CVE-2018-0769;绕过类型检查,如CVE-2017-11802、CVE-2018-17463和CVE-2018-4233;以及各类其他类型漏洞。
模糊测试是一种自动化漏洞挖掘技术。尤其在针对浏览器引擎这类复杂的系统时,模糊测试相比代码审计等其他方式有着更高的挖掘漏洞效率。其核心思想是将随机生成的输入重复提供给应用程序,然后在处理输入直至程序退出期间,监视程序是否出现错误情况。模糊测试主要分为两类,基于生成的方法和基于变异的方法。分述如下:
cdkl5基因突变基于生成的模糊测试方法,每个输入文件都是从头开始生成的,通常遵循一组预定义的规则。该规则将是上下文无关并会限定所有输入的集合。在生成的过程中,通过随机选择实现随机生成。
基于变异的模糊测试方法,是从一组已知良好的种子文件开始,然后以随机方式对它们进行变异。可能的变异包含比特和字节翻转、递增和递减整数值、插入预定义的特殊整数和字符串值等。
在模糊测试程序运行后便会不断生成测试样本,让目标程序执行,获取执行结果并统计。衡量模糊测试对目标程序漏洞挖掘的进度,通常使用的是覆盖率指标。覆盖率是通过桩来计算的,桩存在于目标程序的分支跳转和函数调用处,通常都是在编译目标程序时由编译器完成插桩工作[1]。每次执行目标程序后,模糊测试工具可以获得执行过程中抵达的桩信息,计算抵达过的桩数量相对于总数的占比,即为覆盖率指标。
为了能尽快提高覆盖率,提出了基于覆盖率为导向的模糊测试方法,当样本抵达了新的桩,则将其确定为“有趣”的样本保留,在未来继续对其进行变异,如此往复,逐渐遍历系统的所有空间。
1 研究现状
在现今针对JavaScript引擎的模糊测试工具中,有基于规则生成的[2,3],也有基于变异生成的[4,5,6,7],本节会介绍当今主流的几款针对JavaScript引擎的模糊测试工具[2,6,8],并分析其使用的模糊测试技术。
1.1 CodeAlchemist
这是一款基于语料库的生成模糊测试工具,从JavaScript种子文件中分解出代码单元片段,对其进行变量重命名、数据流分析、类型分析后并放入代码块池中,然后对代码块池中的片段进行随机选择,组合生成JavaScript测试样本。CodeAlchemist在组合代码片段时,会考虑上下文约束,从符合变量类型和数量的代码片段中随机选择。该方法成功提高了模糊测试样本的成功率。
1.2 Fuzzilli
这是一款基于中间语言的模糊测试工具,Fuzzilli定义了一种新的中间语言FuzzIL并在其上进行生成和变异,在组合了一系列中间语言后,统一
第54卷第1期王 越,孙 亮,王轶骏,薛 质:一种针对JavaScript引擎JIT编译器的模糊测试方法
将其提升为JavaScript测试样本。提升过程时基于上下文和类型系统,测试样本有着较高的JavaScript 语义正确性,并且变异过程是基于覆盖率导向的,可以达到较高的覆盖率。
1.3 DIE
这是一款基于类型语法树的变异模糊测试工具,将JavaScript种子文件转为语法树,然后通过类型分析,产生包含类型标识的语法树(Typed AST)。DIE基于类型语法树并保留种子文件结构和类型特征进行变异,优质的样本对于DIE非常重要,故其选择了大量以往的JavaScript崩溃样本。
1.4 分析
城镇化率对于现今针对JavaScript引擎的模糊测试工具而言,测试样本的成功率和覆盖率是重要的衡量指标。对于JavaScript引擎中的JIT编译器,测试样本成功率和覆盖率同样是衡量模糊测试性能的重要指标。其中测试样本成功率指成功进行JIT优化并执行优化代码的样本的比例,而覆盖率指JIT编译器部分的覆盖率。
当今针对JavaScript引擎的模糊测试工具对JIT 引擎的测试样本成功率不高。原因为:(1)JIT引擎需要特殊的条件进行触发,并不是所有测试样本都会触发JIT优化;(2)JIT代码会出现优化退出的情况,而以一个会产生优化退出的样本作为种子文件时,会产生许多不成功的测试样本;(3)生成过长的样本会影响JIT的运行时间而导致超时。
当今针对JavaScript引擎的模糊测试工具对JIT 引擎的覆盖率也不高。原因为:(1)需要拥有优质的JIT种子文件作为变异样本;(2)在模糊测试JIT优化阶段时较为盲目,无法针对某一JIT优化阶段进行专一的探索。
2 设计思路
该节会介绍本模糊测试引擎的设计思路,包含生成JIT种子文件、检测和变异三个部分。
2.1 生成JIT种子文件
从触发JIT优化条件而言,需要一个循环被多次执行,这样在循环内部的代码将会被JIT优化。故设计了一个JIT种子文件的模板,包含:(1)一个将要被优化的opt函数内部;(2)触发JIT优化的循环;(3)外部不被优化的代码。如图2所示,在修改了JavaScript引擎的运行参数后,可以将多次调用的数量减少为10~1000次。
function opt(params) {
宝钢采购电子商务平台
// code generated for JIT optimized
}
// code generated
// trigger JIT
for (let i = 0; i <= 1000; i++) {
opt(params);
}
// code generated
图2 种子文件生成结构
在生成JIT种子文件时,采用基于中间语言的生成方式。相比基于语法或基本块的生成方式,中间语言可以构造更为泛型和复杂的句法结构。另外在从中间语言提升为JavaScript的过程中会考虑上下文约束,每一个变量不仅保存类型信息,还有方法、属性、原型链信息,相比基于类型语法树的方法能够
生成语义正确性更高的样本。如图3显示了如果只通过类型语法树进行生成可能导致的语义错误,由于未考虑到原型链,会认为变量a作为数组类型仍拥有splice方法。
a = [13.37];
a.__proto__ = {};
a.splice(0,1,2);//Uncaught TypeError: a.splice is not a function
图3 单一的类型系统可能发生的语义错误
2.2 检测
在检测上,除了崩溃捕获、运行时长和覆盖率信息,还需要检测JIT优化是否成功执行。JIT编译后会在代码中插入一些检查来确保JIT优化的正确执行,而当检查不被通过时,JIT优化将会被退出,返回到原本的字节码进行逐步解释执行。在这种情况下,该测试样本并没有对JIT编译器进行有效的模糊测试。
JIT种子文件在生成后需要被执行一次,统计其运行时长、覆盖率和JIT执行情况,并以此决定其是否被设置优先级放入变异队列中。如果生成的JIT种子文件没有触发JIT优化或退出JIT优化,则认为对该
种子文件的变异无法有效地对JIT进行模糊测试,将会抛弃该种子文件。当一个JIT种子文件抵达了新的桩,成功执行了JIT优化,并且有较短的运行时长后,该种子文件将会被设置一个较高的优先级放入变异队列中。
通信技术
<2021年
2.3 变异
变异会选择一个JIT种子文件,在不改变其中间语言结构的情况下,重新生成中间语言中可替换的变量,产生新的测试样本。使用该方法的原因是触发JIT优化每个阶段的条件和每一条JIT优化的JavaScript语句都有较大的关系。如果如Fuzzilli在每次变异进行插入、合并等细粒度较大的变异操作,将会大幅修改测试样本结构,从而改变已触发的JIT优化阶段,导致盲目地对JIT优化阶段进行模糊测试。而本方法保持了中间语言结构,并在此之上进行的变异能大概率确保触发的测试样本的JIT 优化阶段和JIT种子文件的JIT优化阶段相同,从而能更深入地探索JIT优化阶段,以达到更高的覆盖率。
种子文件的能量分配规则类似主流的模糊测试工具[9,10]。但对于优化函数内部和外部的能量分配和变
异方式却是不同的。每次对一个种子文件进行变异会执行数次基于中间语言的变异操作,每次操作在优化函数内部的概率会大于在外部的概率。在JIT优化函数内部会采用保留中间语言结构的变异方式,而在优化函数外部则会细粒度大的变异方式。
3 实现
本节会分别叙述本模糊测试工具实现上较为核心的几个部分。
3.1 中间语言
中间语言是一种抽象的操作,本方法定义了如LoadProperty,StoreElement,CallMethod,BeginIf等中间语言,中间语言需要尽可能涵盖JavaScript的各种语言特征,如变量声明、赋值语句、一元操作符、二元操作符、函数调用、方法调用、创建对象、控制流等,如图4所示。
BeginPlainFunction v1[‘Bool’, ‘Bool’]
v2 = LoadElement()
EndFunction
v3 = CallMethod Math abs()
BeginFor(v4 1000)
Call v1()
EndFor
图4 中间语言描述
在生成中间语言后,对其逐条分析其上下文环境,从已有的上下文容器中获取合适的变量,然后再分析该条中间语言生成的返回值变量,将其存入上下文容器中,最终提升为JavaScript语句。
44英寸3.2 上下文容器
系统需要知道每一条中间语言执行后,上下文变量的情况,来确保语义的正确性。通过维持一个容器,在分析中间语言的过程中实时地将上下文变量存储在容器中。容器中存储着JavaScript内置的构造器对象,也会将全局变量和局部变量存储其中。在逐条分析中间语言时,当遇到if-else、for循环、函数声明等会产生新作用域的中间语言,会生成一个新的域环境,在新作用域中生成的变量会被存储在新域环境中。当退出该作用域时,会将该域环境以及其中的变量全部删除。容器同时为系统提供获取当前上下文环境下各种类型的变量接口。
3.3 变量
每一个变量都继承于Variable类,该类包含了变量名、类型、方法、属性、原型链和函数签名。在JavaScript中的内置类型有许多,本方法将其分类为基础的Undefined、Int、Float、String、Object、Boolean、Function、Constructor。另外针对Object对象再根据不同的构造器划分,包含Symbol、Map、Set、ArrayBuffer等。每一种类型都存储了属性名和方法名以及原型链的上一个对象指针。对于内置对象的方法或者自定义的函数,会存储定义方法所需参数和返回值的类型作为函数签名,以便在调用方法时准确地从上下文容器中取出可用的变量。值得注意的是,在调用方法的过程中,需要考虑原型链的规则,优先寻当前对象的方法是否被定义,然后是构造器的方法是否被定义,再寻内置的方法。如果没有则去寻原型链上一个对象的构造器方法直至到达原型链头节点。如图5所示,定义了JavaScript中Array的内置方法,在该对象中,键名对应着方法名,值对应着参数列表的类型,数组最后一项为返回值类型。
// JSArray method
copyWithin: [int, int, opt(int), arr],
entries: [arr],
every: [func, opt(object), bool],
硝酸镁...
图5 系统对JavaScript内置方法的描述
3.4 程序执行
生成测试样本算法如图6所示。
图8 测试样本成功率和超时率统计
考虑在所有测试样本中,成功触发JIT优化的比例,统计结果如图9所示,JITFuzz相比Code Alchemist、DIE、Fuzzilli都有更高的JIT成功率。这说明本方法采用生成JIT种子文件和基于中间语言结构的变异方法所产生的样本,有更高的成功执行JIT优化的概率。
此外,JITFuzz和Fuzzilli分析比较了模糊测试的JIT覆盖率情况。通过对JavaScript引擎中JIT编

本文发布于:2024-09-22 01:24:29,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/1700.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:优化   测试   方法
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议