《一种针对JavaScript引擎JIT编译器的模糊测试方法.docx》由会员分享,可在线阅读,更多相关《一种针对JavaScript引擎JIT编译器的模糊测试方法.docx(13页珍藏版)》请在优知文库上搜索。
1、Web浏览器安全是用户在网络环境中至关重要的一环,而JaVaSCriPt引擎是浏览器中的重要组件,攻击者可以通过钓鱼网页轻易地让用户触发JavaScript引擎漏洞。JaVaSCriPt引擎又是内存危险的,触发漏洞后攻击者可以构造特殊的原语来实现内存的任意读写,从而控制被攻击者的设备.JavaScript引擎漏洞在近几年频繁出现,伴随的利用脚本都仅仅需要远程浏览器访问,范围圈盖WindOWs、MaCOS、iOS、AndrOid各种操作系统,故JaVaSeriPt引擎的安全问题已经是安全研究的重点对象。近几年来,JavaScript引擎漏洞中JIT编译器的漏洞占据了越来越大的比重.JIT编译器,
2、全称(JUStTn-Time)是一种程序语言提高运行效率的方法。如图1所示,JavaScript引擎解糅执行JavaScript的流程为:先通过词法和语法分析将JavaScript脚本转化为AST树,然后编译为中间语言字节码,接着进行逐步解糅执行,当执行的过程出现多次循环或者多次函数调用时,JIT编译器会将该部分字节码重新编译,通过编译优化提升运行效率,圾终转化为符合操作系统的机蹲码并执行。H1.IwiMfJavaScriptMaJ1.T优化阶段,J1.T会将优化拆分成为多个步骤(如常数折段、循环不变量提升等),这些步骤即为每一个具体的JIT优化阶段.JIT优化时会将需要优化的代码进行分析,当
3、其满足优化阶段的条件时,进行优化。J1.T编译器漏洞,主耍包含的是JIT优化相关的漏洞,优化漏洞通常在J1.T编译优化过程中利用错误预测或绕过检查而达到利用。其中包含绕过边界检查,如CVE-2015-0817、CYE-2017-2547和CYE-2018-0769:绕过类型检查,如CYE-2017-11802、CYE-2018-17163和CvE-2018-4233;以及各类其他类型漏洞。模树测试是一种自动化漏涧挖掘技术。尤其在针时浏览器引擎这类史杂的系统时,模糊测试相比代码审计等其他方式有着更高的挖掘漏洞效率。其核心思想是将随机生成的输入重史提供给应用程序,然后在处理输入直至程序退出期间,监
4、视程序是否出现错误情况。模糊测忒主要分为两类,基于生成的方法和基于变异的方法。分述如卜丁基丁生成的模糊测试方法,每个输入文件都是从头开始生成的,通常遵循一组预定义的规则。该规则将是上卜.文无关并会限定所有输入的集合。在生成的过程中,通过随机选择实现随机生成.基丁变异的模糊测试方法,是从一组己知良好的种子文件开始,然后以随机方式对它们进行变异。可能的变异包含比特和字节翻转、递增和递减整数值、插入预定义的特殊整数和字符申值等.在模糊测试程序运行后便会不断生成测限样本,让目标程序执行,获取执行结果并统计。衡量模糊测成对目标程序漏洞挖掘的进度,通常使用的是覆盖率指标.覆盖率是通过桩来计算的,林存在于目
5、标程序的分支跳转和函数调用处,通常都是在编译目标程序时由编译器完成插桩工作.每次执行目标程序后,模糊测式工具可以获得执行过程中抵达的桃信息,计算抵达过的桩数量相对于总数的占比,即为覆盖率指标。为能尽快提高罹盖率,提出了基年盖率为导向的模糊测试方法,当样本抵达了新的枇,则将其确定为“有趣”的样本保留,在未来继续对其进行变异,如此往熨,逐渐遍历系统的所有空间0O1.研究现状在现今的对JaVaSCriPt引擎的模树测试工具中,有基于规则生成的,也有基丁变异生成的,本节会介绍当今主流的几款针对JaVaSCriPt引擎的模糊测试工具,并分析其使用的模糊测试技术。1.1 CodeAIchemist这是一款
6、基于语料库的牛成模糊测试工具,从JaVaSCriPt种子文件中分解出代码单元片段,对其进行变量重命名、数据流分析、类型分析后并放入代码块池中,然后对代码块池中的片段进行随机选择,组合生成JavaScript测试样本。COdeAIChemiSt在组合代码片段时,会考虑上下文约束,从符合变量类型和数属的代码片段中随机选择。该方法成功提高了模糊测试样本的成功率。1.2 Fuzzi1.1.i这是一款基于中间语言的模糊测试工具,Fuzzi1.1.i定义了一种新的中间语言FUZZI1.并在其上进行生成和变异,在组合了一系列中间语言后,统一将其提升为JaVaSeriPt测试样本。提升过程时基于上卜.文和类型
7、系统,测试样本有着较高的JaVaSCriPt语义正确性,并且变异过程是基于覆盖率导向的,可以达到较高的覆盖率。1.3 DIE这是一款基于类型语法树的变异模糊测试工具,将JaVaSCriPt种子文件转为语法树,然后通过类型分析,产生包含类型标识的语法树(TypedAST)。DIE基于类型语法树并保留种子文件结构和类型特征进行变异,优质的样本对于DIE非常重要,故其选择大量以往的JavaScript崩溃样本.1.4 分析时丁现今针对JaVaSCriP1.引擎的模糊测试工具而言,测试样本的成功率和覆盖率是重要的衡量指标。对于JaVaSCriPt引擎中的Jrr编译器,测试样本成功率和覆盖率同样是衡是模
8、糊测武性能的重耍指标,其中测试样本成功率指成功进行JIT优化并执行优化代码的样本的比例,而覆盖率指J1.T编译器部分的覆盖率。当今针对JaVaSCriPt引擎的模糊测试工具对J1.T引擎的测试样本成功率不高。原因为:(I)JIT引擎需要特殊的条件进行触发,并不是所有测试样本都会触发J1.T优化:(2)JIT代码会出现优化退出的情况,而以一个会产生优化退出的样木作为种子文件时,会产生许多不成功的测试样本:(3)生.成过长的样本会影响J1.T的运行时间而导致超时。当今针对JaVasCriPt引擎的模糊测试工具对Jrr引擎的覆盖率也不高。原因为:(I)需要拥有优质的J1.T种子文件作为变异样本:(2
9、)在模糊测试JIT优化阶段时较为盲目,无法针对某一Jrr优化阶段进行专一的探索。1.5 2设计思路该节会介绍本模糊测试引擎的设计思路,包含生成Jrr种子文件、检测和变异三个部分。2.1生成J1.T种子文件从触发J1.T优化条件而言,需要一个循环被多次执行,这样在循环内部的代码将会被JIT优化.故设计了一个Jn种子文件的模板,包含:(1)一个将要被优化的。Pt函数内部:(2)触发Jrr优化的循环;(3)外部不被优化的代码。如图2所示,在修改JavaScript引擎的运行参数后,可以将多次调用的数量减少为101000次。在生成JIT种子文件时,采用基于中间语言的生成方式。相比基丁语法或基本块的生成
10、方式,中间语言可以构造更为泛型和复杂的句法结构。另外在从中间语言提升为JaVaSCriPt的过程中会考虑上卜.文约束,每一个变量不仅保存类型信息,还有方法、属性、原型链信息,相比基于类型语法树的方法能够牛.成语义正确性更高的样本。如图3显示了如果只通过类型语法树进行生成可能导致的语义错误,由于未考虑到原型链,会认为变量a作为数组类型仍拥有SPIiCe方法。图2种子文件生成结构a=1337;*-K5*o_=0;Asphc-OJJ):IncUghtTypeError:a.spkeisnotaftmco图3单一的类型系统可能发生的语义错误2.2检测在检测上,除了崩溃捕获、运行时长和覆盖率信息,还需要
11、检测J1.T优化是否成功执行。JIT编译后会在代码中插入一些检查来确保JIT优化的正确执行,而当检查不被通过时,JIT优化将会被退出,返回到原本的字节码进行逐步解释执行。在这种情况下,该测试样本并没有对JIT编译器进行有效的模糊测试。JIT种子文件在生成后需要被执行次,统计其运行时长、圈盖率和JIT执行情况,并以此决定其是否被设置优先级放入变异队列中。如果生成的J1.T种子文件没有触发JIT优化或退出JIT优化,则认为对该种子文件的变异无法有效地对J1.T进行模糊测试,揩会抛弃该种子文件。当一个JIT种子文件抵达了新的桩,成功执行了Jrr优化,并I1.有较短的运行时长后,该种子文件将会被设置个
12、较高的优先级放入变异队列中。2.3 变异变异会选择一个J1.T种子文件,在不改变其中间语言结构的情况下,重新生成中间语言中可昔换的变量,产生新的测试样本。使用该方法的原因是触发JIT优化每个阶段的条件和每一条JIT优化的JavaScript语句都有较大的关系如果如FUZZiUi在每次变异进行插入、合并等细粒度较大的变异操作,将会大幅修改测试样本结构,从而改变已触发的JIT优化阶段,导致盲目地对JIT优化阶段进行模糊测忒。而本方法保持了中间语言结构,并在此之上进行的变异时大概率确保触发的测试样本的JIT优化阶段和JIT种子文件的J1.T优化阶段相同,从而能更深入地探索JIT优化阶段,以达到更高的
13、覆盖率。种子文件的能量分配规则类似主流的模糊测试工具.但对下优化函数内部和外部的能量分配和变异方式却是不同的。每次对一个种子文件进行变异会执行数次基于中间语言的变异悌作,每次操作在优化函数内部的概率会大T在外部的概率.在J1.T优化函数内部会采用保留中间语言结构的变异方式,而在优化函数外部则会细粒度大的变异方式。O3实现本节会分别叙述本模糊测试工具实现上较为核心的几个部分。3.1 中间语言中间语言是一种抽象的操作,本方法定义(如1.oadPrOPerty,StoreE1.ement,Ca1.1.Method,BeginIf等中间语言,中间语言需要尽可能涵盖JaVaSCriPt的各种语言特征,如
14、变量声明、赋值语句、一元操作符、二元操作符、函数调用、方法调用、创建对象、控制流等,如图4所示。在生成中间语言后,对其逐条分析其上卜.文环境,从已有的上F文容器中获取合适的变量,然后再分析该条中间语言生成的返回值变量,将其存入上下文容器中,最终提升为JaVaSCriPt语句。BesinPIainFunctionV1.,Boo1.Boo1.,1.v2三功州照期期0EndFunctioav3-Ca1.1.MethodMathabsOBe*ginFov41000)CaDv1.OEJ!*B4中间通言据建3.2上下文容器系统需要知道每一条中间语言执行后,上卜.文变量的情况,来确保语义的正确性。通过维持一
15、个容器,在分析中间语言的过程中实时地将上下文变量存储在容器中。容器中存储者JaVaSCriPt内置的构造潜对象,也会将全局变量和局部变疥存储其中。在逐条分析中间语言时,当遇到if-e1.se、for循环、函数声明等会产生新作用域的中间语言,会牛.成一个新的域环境,在新作用域中生成的变员会被存储在新域环境中.当退出该作用域时,会将该域环境以及其中的变量全部删除。容器同时为系统提供获取当前上卜.文环境卜各种类型的变量接口。3.3 变量每一个变量都继承于VariabIe类,该类包含了变量名、类型、方法、属性、原型链和函数签名.在JaVaSCriPt中的内置类型有许多,本方法将其分类为基础的Undef
16、ined、Int、F1.oat、String、ObjeCC、BooIean、FUnCCionConstructor。另外针对ObjeCt对象再根据不同的构造器划分,包含SymbO1、Map、Set、ArrayBuffer等。每一种类型都存储了属性名和方法名以及原型链的上一个对象指针.对手内置对象的方法或者白定义的函数,公存储定义方法所需参数和返PI值的类型作为函数签名,以便在谢用方法时准硬地从上卜文容器中取出可用的变ft.值得注意的是,在调用方法的过程中,需要考虑原型链的规则,优先寻找当前对象的方法是否被定义,然后是构造器的方法是否被定义,再寻找内置的方法。如果没有则去寻找原型链上一个对象的构造器方法直至到达原型链头节点.如图5所示,定义了JaVaSCriPt中Array的内置方法,在该对象中,键名对应者方法名,值对应若参数列