王聰沖,甘水滔,王曉鋒
1江南大學(xué)人工智能與計(jì)算機(jī)學(xué)院 無(wú)錫 中國(guó) 214122 2數(shù)字工程與先進(jìn)計(jì)算國(guó)家重點(diǎn)實(shí)驗(yàn)室 無(wú)錫 中國(guó)214083
JavaScript引擎是瀏覽器的必要組成部分,其安全性一直備受關(guān)注[1],由于其代碼量巨大、邏輯極其復(fù)雜,導(dǎo)致漏洞挖掘技術(shù)發(fā)展一直無(wú)法滿足JavaScript引擎的安全測(cè)試需求,針對(duì)JavaScript引擎漏洞攻擊事件層出不窮。通過(guò)對(duì) CVE漏洞庫(kù)統(tǒng)計(jì),暴露在 Jerryscript[2]、ChakraCore[3]、SpiderMonkey[4]、JavaScriptCore[5]、V8[6]其高危漏洞條目超過(guò) 450條,其中ChakraCore和V8的數(shù)量分別超過(guò)150條和200條。并且在2020年上半年暴露的高危漏洞數(shù)量已超過(guò)2019年全年暴露的總數(shù)。具體如圖1所示。通過(guò)進(jìn)一步對(duì)過(guò)去JavaScript引擎漏洞暴露來(lái)源調(diào)查,模糊測(cè)試是發(fā)現(xiàn)JavaScript引擎漏洞的主流自動(dòng)化檢測(cè)方法[7]。
圖1 主流JavaScript引擎的CVE漏洞暴露統(tǒng)計(jì)情況Figure 1 CVE vulnerability exposure statistics for mainstream JavaScript engines
模糊測(cè)試[8]通過(guò)不斷自動(dòng)構(gòu)造隨機(jī)非預(yù)期的輸入數(shù)據(jù)給目標(biāo)軟件,實(shí)時(shí)監(jiān)視目標(biāo)軟件運(yùn)行異常信號(hào),能有效發(fā)現(xiàn)軟件存在的脆弱性[9]。模糊測(cè)試主要分為黑盒和灰盒模型,在2014年以前基本以黑盒模型為主,黑盒模型不具備程序信息反饋能力,具有運(yùn)行速度快,能適應(yīng)復(fù)雜規(guī)模代碼軟件等優(yōu)點(diǎn),但測(cè)試效率一直受限于隨機(jī)性過(guò)大、代碼覆蓋能力弱等問(wèn)題[10]。從 2015年開(kāi)始,自經(jīng)典灰盒測(cè)試系統(tǒng)AFL[11]問(wèn)世以來(lái),通過(guò)路徑覆蓋信息實(shí)時(shí)反饋,在文檔解析、圖片解析、音頻解析等文件型輸入的軟件目標(biāo)測(cè)試過(guò)程中達(dá)到較高代碼覆蓋率,發(fā)現(xiàn)大量未公開(kāi)漏洞,并實(shí)現(xiàn)了向協(xié)議型[12]和內(nèi)核型[13]對(duì)象應(yīng)用擴(kuò)展?;液心P鸵阎鸩匠蔀樽钣行У闹髁髂:郎y(cè)試手段,并且和 libFuzzer[14]、honggfuzz[15]等灰盒工具集成在谷歌的可持續(xù)開(kāi)源模糊測(cè)試服務(wù)OSS-fuzz[16]中,截止到2020年6月,OSS-fuzz已經(jīng)在300個(gè)開(kāi)源項(xiàng)目中發(fā)現(xiàn)了上萬(wàn)個(gè)可觸發(fā)漏洞[17]。
模糊測(cè)試在JavaScript引擎的應(yīng)用方法同樣劃分為黑盒和灰盒模型兩類,其難點(diǎn)在于如何高效的生成并測(cè)試高質(zhì)量的JavaScript代碼測(cè)試用例。不同于文檔解析等文件型測(cè)試?yán)?JavaScript代碼需要遵從嚴(yán)格的語(yǔ)法規(guī)范。JavaScript引擎在解析 JavaScript代碼過(guò)程中,一旦遇見(jiàn)不符合JavaScript語(yǔ)法規(guī)則代碼,就會(huì)終止對(duì)整個(gè)測(cè)試?yán)慕馕?從而無(wú)法觸及JavaScript引擎的關(guān)鍵功能模塊,難以達(dá)到理想的測(cè)試效果。然而,如果直接采用 AFL等灰盒工具的字節(jié)或比特級(jí)隨機(jī)變異策略,極易破壞JavaScript代碼的合法性,導(dǎo)致JavaScript引擎測(cè)試過(guò)程中效率極其低下。因此,JavaScript引擎模糊測(cè)試在過(guò)去以基于代碼生成的黑盒模型為主,代表性工具有JSfunfuzz[18]、LangFuzz[19]、CodeAlchemist[20]。JSfunfuzz 通過(guò)JavaScript代碼語(yǔ)法模板生成測(cè)試用例,容易產(chǎn)生合法的JavaScript代碼,但需要花費(fèi)大量的人力構(gòu)建語(yǔ)法模板,而且容易漏掉有價(jià)值的語(yǔ)法模式。LangFuzz通過(guò)對(duì)已有合法JavaScript代碼進(jìn)行解析,轉(zhuǎn)換為抽象語(yǔ)法樹(shù)形式,將樣本拆分成子樹(shù)代碼片段放入代碼池中,并不斷使用代碼池中的子樹(shù)替代當(dāng)前測(cè)試用例的非終止節(jié)點(diǎn)來(lái)構(gòu)建新的測(cè)試用例,這種方式極大提升了測(cè)試?yán)詣?dòng)生成能力,但仍然容易產(chǎn)生非法的代碼,CodeAlchemist進(jìn)一步引入控制流和數(shù)據(jù)流分析,定位和緩解未定義變量問(wèn)題,進(jìn)一步提升了代碼生成的正確性。但總體來(lái)說(shuō),黑盒模型難以擺脫執(zhí)行速度慢和代碼覆蓋能力弱等缺點(diǎn)。
為了彌補(bǔ)JavaScript引擎黑盒模型的不足,軟工頂級(jí)會(huì)議工作Superion[21]構(gòu)建了基于JavaScript代碼子樹(shù)變異的灰盒模型,在 AFL模型中增加了子樹(shù)變異階段,以子樹(shù)替代的方式去對(duì)種子變異,一定程度降低了AFL的JavaScript代碼生成錯(cuò)誤概率,同等測(cè)試環(huán)境下,其代碼覆蓋和漏洞發(fā)現(xiàn)能力明顯優(yōu)于黑盒模型。然而,Superion在變異階段對(duì)子樹(shù)類型并不敏感,這種盲目的子樹(shù)替換策略導(dǎo)致生成的代碼出現(xiàn)嚴(yán)重的類型錯(cuò)誤和語(yǔ)法錯(cuò)誤。
基于現(xiàn)有JavaScript引擎灰盒模型的不足,本文提出了一種基于子樹(shù)類型敏感的JavaScript引擎灰盒測(cè)試技術(shù),并且實(shí)現(xiàn)了灰盒測(cè)試系統(tǒng)ILS。ILS在路徑反饋的模糊測(cè)試框架基礎(chǔ)上[22],通過(guò)對(duì) JavaScript代碼進(jìn)行精準(zhǔn)語(yǔ)法分析,對(duì)子樹(shù)集合進(jìn)行類型識(shí)別和分類,并且在變異階段構(gòu)建了子樹(shù)類型敏感的變異策略,使用同類型子樹(shù)進(jìn)行覆蓋變異,不僅大幅提升了測(cè)試種子的有效率,而且?guī)?lái)了更高的代碼覆蓋能力和漏洞發(fā)現(xiàn)能力。本文挑選了Jerryscript、ChakraCore和JavaScriptCore三個(gè)常用JavaScript引擎作為測(cè)試對(duì)象,通過(guò)對(duì) ILS和 CodeAlchemist、Superion等工具進(jìn)行24 h性能測(cè)試對(duì)比,實(shí)驗(yàn)表明:在保持灰盒模型執(zhí)行性能優(yōu)勢(shì)的情況下,錯(cuò)誤率比Superion降低了36%,比CodeAlchemist降低了21%。在代碼行覆蓋率上,ILS相比Superion提升了72%,相比CodeAlchemist提升48%; 在函數(shù)覆蓋率上,ILS相比 Superion提升 80%,相比 CodeAlchemist提升50%。在漏洞發(fā)現(xiàn)數(shù)量上,ILS相比Superion提升了100%。最后,ILS在這三個(gè)JavaScript引擎上總共發(fā)現(xiàn)了 26個(gè)未知 Bug,并均得到了廠商的確認(rèn)和修復(fù)。
本文的貢獻(xiàn)總結(jié)如下:
1) 面向 JavaScript引擎對(duì)象,提出了一種子樹(shù)類型敏感的灰盒測(cè)試模型,并實(shí)現(xiàn)了相應(yīng)原型系統(tǒng)ILS。
2) 與經(jīng)典黑盒和灰盒測(cè)試工具相比,ILS能顯著降低JavaScript代碼測(cè)試用例的錯(cuò)誤率,并且能大幅提高JavaScript引擎的代碼覆蓋能力。
本節(jié)先對(duì) JavaScript引擎的基本工作原理進(jìn)行描述,然后對(duì) JavaScript引擎漏洞挖掘方法相關(guān)工作進(jìn)行總結(jié),最后進(jìn)一步說(shuō)明本文方法和傳統(tǒng)方法的差異。
JavaScript引擎是瀏覽器重要組成部分,是根據(jù) ECMAScript[23]定義的語(yǔ)言標(biāo)準(zhǔn)來(lái)動(dòng)態(tài)執(zhí)行JavaScript字符串的重要程序。JavaScript引擎具有代碼量大,工作原理和邏輯結(jié)構(gòu)復(fù)雜等特點(diǎn)。JavaScript引擎動(dòng)態(tài)解析JavaScript代碼過(guò)程可以分為語(yǔ)法檢查階段和運(yùn)行階段,語(yǔ)法檢查階段包括詞法分析和語(yǔ)法分析,運(yùn)行階段包括預(yù)解析和實(shí)際執(zhí)行。其具體工作流程如圖2所示: JavaScript引擎首先對(duì) JavaScript代碼進(jìn)行語(yǔ)法分析得到抽象語(yǔ)法樹(shù)(Abstract Syntax Tree,AST),然后進(jìn)一步解析得到字節(jié)碼(bytecode),在生成字節(jié)碼的同時(shí),優(yōu)化編譯器生成高度優(yōu)化的機(jī)器代碼,生成的機(jī)器代碼最后替換原來(lái)的字節(jié)碼。JavaScript引擎在優(yōu)化代碼的時(shí)候會(huì)使用未優(yōu)化的字節(jié)碼進(jìn)行工作,有效提高了JavaScript引擎性能。
圖2 JavaScript引擎工作流程Figure 2 JavaScript engine workflow
在JavaScript解析過(guò)程中,一旦遇到錯(cuò)誤后面的代碼就無(wú)法執(zhí)行。在ECMAScript標(biāo)準(zhǔn)中定義了5種運(yùn)行時(shí)錯(cuò)誤: 語(yǔ)法錯(cuò)誤(SyntaxError)、范圍錯(cuò)誤(RangeError)、引用錯(cuò)誤(ReferenceError)、類型錯(cuò)誤(TypeError)和URI錯(cuò)誤(URIError)。如圖3所示: 第1行中,var后面沒(méi)有申明變量,直接進(jìn)行賦值操作,不符合語(yǔ)法規(guī)則,就會(huì)拋出語(yǔ)法錯(cuò)誤; 第2行中,一旦變量數(shù)值超出有效范圍,便會(huì)拋出范圍錯(cuò)誤; 第 3行中,一旦引用一個(gè)不存在的變量時(shí),便會(huì)拋出引用錯(cuò)誤; 第4行中,當(dāng)值的類型或參數(shù)不是預(yù)期類型時(shí),便會(huì)拋出類型錯(cuò)誤; 第5行中,使用全局URI處理函數(shù)遇見(jiàn)不正確參數(shù)時(shí),便會(huì)拋出URI錯(cuò)誤。由于URI錯(cuò)誤很少在JavaScript解析過(guò)程中出現(xiàn),因此本文只考慮前4種錯(cuò)誤類型。
圖3 JavaScript引擎解析代碼過(guò)程中常見(jiàn)的運(yùn)行時(shí)錯(cuò)誤類型Figure 3 Common runtime errors in the process of JavaScript engine parsing code
經(jīng)典程序分析方法符號(hào)執(zhí)行[24-27]和污點(diǎn)分析[28-31]需要對(duì)測(cè)試軟件的指令進(jìn)行逐條解析,分析速度慢,當(dāng)處理復(fù)雜代碼對(duì)象JavaScript引擎,符號(hào)執(zhí)行極其容易受限于路徑爆炸和復(fù)雜約束不可解問(wèn)題,污點(diǎn)分析極易遭受內(nèi)存爆炸、過(guò)度污染和欠污染問(wèn)題[32],難以在JavaScript引擎分析中產(chǎn)生作用,在過(guò)去鮮有針對(duì)JavaScript引擎的符號(hào)執(zhí)行和污點(diǎn)分析工作。另外,經(jīng)典靜態(tài)分析工具 Coverity[33]、Klockwork[34]、Fortify[35]只對(duì)程序語(yǔ)言敏感,因此也能適用于JavaScript引擎分析,但虛報(bào)率高,需要大量人力去驗(yàn)證靜態(tài)報(bào)告的真實(shí)性。針對(duì)JavaScript引擎適配和優(yōu)化的靜態(tài)分析工作[36-38]更多關(guān)注如何降低JavaScript引擎運(yùn)行開(kāi)銷。
相比之下,模糊測(cè)試具有速度快、能適應(yīng)于復(fù)雜代碼對(duì)象等優(yōu)勢(shì),具備直接發(fā)現(xiàn)可觸發(fā)漏洞的能力。因此,本文在相關(guān)工作部分主要關(guān)注模糊測(cè)試方法,從測(cè)試?yán)煞椒ㄉ峡?模糊測(cè)試大體可分為基于變異的模糊測(cè)試方法和基于生成的模糊測(cè)試方法,以下分別針對(duì)JavaScript引擎對(duì)這兩類相關(guān)工作進(jìn)行歸納。
2.2.1 基于生成的模糊測(cè)試方法
基于生成的模糊測(cè)試方法借助手工構(gòu)建的輸入語(yǔ)法模型生成有效的輸入數(shù)據(jù),在一個(gè)理想的輸入語(yǔ)法模型支持下,才能測(cè)試重要功能模塊。在JavaScript引擎模糊測(cè)試應(yīng)用上,基于生成的模糊測(cè)試技術(shù)一直是發(fā)展的重點(diǎn),主要發(fā)展路線可概括為以下三點(diǎn): 1)不斷提升語(yǔ)法模型的自動(dòng)化生成能力;2)不斷豐富生成的 JavaScript代碼模式; 3)不斷消減JavaScript代碼的錯(cuò)誤率。
在代碼自動(dòng)生成能力提升方面,早期的代表性工具有 Peach[39],在應(yīng)用到 JavaScript引擎測(cè)試上,需要為每個(gè)對(duì)象創(chuàng)建模板文件,需要?jiǎng)澐趾秒S機(jī)字段和確定字段,這將消耗大量的人力和時(shí)間成本。JSfunfuzz基于JavaScript語(yǔ)法模板,根據(jù)公開(kāi)漏洞樣本中學(xué)習(xí)已有特征生成測(cè)試用例,只能適應(yīng)SpiderMonkey解析引擎,擴(kuò)展性能力差。CodeAlchemist、DIE[40]等方法通過(guò)對(duì)初始代碼樣本構(gòu)建語(yǔ)法特征抽象模型,盡量保留有價(jià)值的控制流和數(shù)據(jù)流特征,在該基礎(chǔ)上構(gòu)建變異策略生成新的代碼樣本; Skyfire[41]、Montage[42]等方法進(jìn)一步提升了代碼生成的自動(dòng)化能力,在已有訓(xùn)練代碼樣本基礎(chǔ)上,采用學(xué)習(xí)的方式生成新的代碼樣本; 以上幾種方法對(duì)初始代碼樣本極其敏感,人力成本主要體現(xiàn)在初始代碼樣本篩選上,在實(shí)際應(yīng)用過(guò)程中,這些模型更多借助標(biāo)準(zhǔn)測(cè)試集和公開(kāi)漏洞觸發(fā)樣本,最后均達(dá)到了較為理想的代碼生成效果。
在 JavaScript代碼語(yǔ)法模式生成能力方面,Peach、JSfunfuzz主要依賴已有語(yǔ)法模板,不容易推導(dǎo)新的語(yǔ)法模式。Skyfire利用帶概率的上下文敏感語(yǔ)法(PCSG)從大量樣本中學(xué)習(xí)語(yǔ)法和語(yǔ)義規(guī)則,在代碼生成過(guò)程中優(yōu)先選擇低概率的語(yǔ)義產(chǎn)生規(guī)則以生成分布合理的測(cè)試用例。CodeAlchemist會(huì)按照J(rèn)avaScript語(yǔ)句的粒度分解種子文件,針對(duì)每個(gè)塊語(yǔ)句生成多種變體提升代碼塊的豐富性,通過(guò)對(duì)多個(gè)代碼塊組合產(chǎn)生嵌套循環(huán)等結(jié)構(gòu)。Montage從Test262[43]數(shù)據(jù)集中收集了超過(guò)3萬(wàn)個(gè)JavaScript代碼樣本,通過(guò)對(duì)代碼樣本中變量和函數(shù)等標(biāo)識(shí)符重新命名和子樹(shù)分片,形成 LSTM 模型的初始訓(xùn)練數(shù)據(jù),能有效學(xué)習(xí)出JavaScript代碼中的控制流和數(shù)據(jù)流依賴關(guān)系,從而推導(dǎo)出傳統(tǒng)模型能力之外的語(yǔ)法模式,該系統(tǒng)經(jīng)過(guò)一個(gè)半月的測(cè)試,共發(fā)現(xiàn)了 34個(gè)未知Bug。DIE以公開(kāi)漏洞庫(kù)可觸發(fā)漏洞樣本為基礎(chǔ),識(shí)別并保留其中隱式的循環(huán)、特定跳轉(zhuǎn)結(jié)構(gòu)信息以及抽象語(yǔ)法樹(shù)類型信息,這些特征的保留有助于模糊測(cè)試階段集中在容易引發(fā)脆弱性的功能模塊(JIT優(yōu)化模塊)上進(jìn)行,最后發(fā)現(xiàn)了48個(gè)未知Bug。
在JavaScript代碼錯(cuò)誤率消減方面,JSfunfuzz在已有種子模板基礎(chǔ)上,結(jié)合實(shí)現(xiàn)預(yù)先準(zhǔn)備好的函數(shù)、對(duì)象、操作符等JavaScript代碼特征庫(kù),隨機(jī)填充可寫(xiě)字段,生成可用測(cè)試?yán)?由于缺乏各語(yǔ)句和語(yǔ)句間的合法性檢查,這種方式會(huì)帶來(lái)較嚴(yán)重的語(yǔ)法錯(cuò)誤、引用錯(cuò)誤和類型錯(cuò)誤。LangFuzz在生成代碼的過(guò)程中,用當(dāng)前已有的變量去替代生成的代碼片段中未知變量,但無(wú)法避免變量在使用后才聲明,而且會(huì)增加該變量對(duì)象的重復(fù)使用概率,從而導(dǎo)致大量的引用錯(cuò)誤。Skyfile在生成測(cè)試用例的過(guò)程中,也沒(méi)有考慮變量定義、使用等情況,同樣容易造成運(yùn)行時(shí)錯(cuò)誤。針對(duì)這一問(wèn)題,CodeAlchemist提出使用數(shù)據(jù)流分析技術(shù)確定未定義變量和已定義變量,并結(jié)合運(yùn)行時(shí)插樁技術(shù)探測(cè)已執(zhí)行變量的類型。CodeAlchemist在 JavaScript代碼生成過(guò)程中,不斷向代碼尾部擴(kuò)展代碼片段,每次擴(kuò)展代碼片段都會(huì)確保其中的變量在之前已經(jīng)被定義并且具備正確的類型,CodeAlchemist的優(yōu)化方法能有效降低LangFuzz方法中存在的錯(cuò)誤率,相比 JSfunfuzz,能生成超出 5倍以上的有效測(cè)試?yán)?。Montage采用LSTM 模型推導(dǎo)不同代碼片段之間的關(guān)聯(lián)關(guān)系,能有效學(xué)習(xí)出類似變量定義和使用的先后次序等信息,有效降低非學(xué)習(xí)代碼生成策略存在的引用錯(cuò)誤率。DIE通過(guò)保留的結(jié)構(gòu)化語(yǔ)義和類型信息,能有效提升變異的準(zhǔn)確性,大幅增加了種子的有效率,相比CodeAlchemist,可以降低一半的代碼錯(cuò)誤率。
2.2.2 基于變異的模糊測(cè)試方法
基于變異的模糊測(cè)試方法[44-48]通過(guò)對(duì)已有的測(cè)試?yán)M(jìn)行隨機(jī)變異產(chǎn)生新的測(cè)試?yán)?可以不依賴輸入語(yǔ)法模型,正由于其模型簡(jiǎn)單易用,對(duì)人工經(jīng)驗(yàn)依賴小,相比基于生成的模糊測(cè)試方法而言,在非結(jié)構(gòu)化語(yǔ)法輸入對(duì)象中應(yīng)用尤為廣泛[49-51]。但對(duì)于JavaScript代碼等結(jié)構(gòu)化語(yǔ)法輸入,變異策略需要考慮結(jié)構(gòu)化語(yǔ)法特征,不然會(huì)引發(fā)嚴(yán)重的錯(cuò)誤率。在JavaScript引擎模糊測(cè)試應(yīng)用上,基于變異的模糊測(cè)試技術(shù)發(fā)展歷程可概括為: 1)從黑盒模型逐步轉(zhuǎn)向帶路徑覆蓋信息反饋的灰盒模型; 2)從隨機(jī)變異策略逐步發(fā)展為JavaScript代碼語(yǔ)法語(yǔ)義敏感的變異策略。
IFuzzer[52]為針對(duì)JavaScript引擎的黑盒模型,首先把JavaScript代碼樣本轉(zhuǎn)換為樹(shù)的形式,再采用遺傳算法對(duì)測(cè)試樣本進(jìn)行選擇、交叉和變異,選擇階段主要參考適應(yīng)度函數(shù)值大小對(duì)代碼樣本進(jìn)行優(yōu)先選擇,并對(duì)代碼中子樹(shù)節(jié)點(diǎn)進(jìn)行交叉變異生成新的測(cè)試?yán)?該方法和LangFuzz相比,發(fā)現(xiàn)了SpiderMonkey上 LangFuzz之外的 16個(gè)未知 Bug。Fuzzilli[53]會(huì)把JavaScript代碼樣本轉(zhuǎn)換為中間代碼,中間代碼的每條指令由輸入變量、操作碼以及輸出變量構(gòu)成,在中間代碼上進(jìn)行變異不僅有助于繼承已有控制流和數(shù)據(jù)流特征,還能降低代碼錯(cuò)誤率。不同于AFL,Fuzzilli在測(cè)試過(guò)程中忽略了邊的循環(huán)次數(shù),這樣容易丟失覆蓋JIT優(yōu)化功能模塊的高價(jià)值測(cè)試?yán)=鼛啄陿I(yè)界在JavaScript引擎模糊測(cè)試的變異策略上增加了子樹(shù)分析,以子樹(shù)為變異單位進(jìn)行變異操作,如 Montage、CodeAlchemist、Nautilus、Superion。其中,Superion充分發(fā)揮AFL的優(yōu)勢(shì),在其基礎(chǔ)上添加子樹(shù)變異階段,和AFL、JSfunfuzz對(duì)比,大幅提升JavaScript引擎對(duì)象上的代碼覆蓋能力和漏洞發(fā)現(xiàn)能力。但以上工作普遍沒(méi)有對(duì)子樹(shù)進(jìn)行類型分析,對(duì)子樹(shù)類型的不敏感會(huì)極大削弱變異策略的種子生成效率。
根據(jù)以上相關(guān)工作分析可知,子樹(shù)變異和路徑覆蓋反饋能力是當(dāng)前多個(gè)JavaScript引擎模糊測(cè)試的重要方法特征,但這些工作普遍缺乏對(duì)子樹(shù)的類型分析,容易導(dǎo)致嚴(yán)重的 JavaScript代碼錯(cuò)誤率,從而丟失一些子樹(shù)類型敏感的脆弱路徑。本文根據(jù)當(dāng)前工作的不足,構(gòu)建了一個(gè)具備子樹(shù)敏感變異能力和路徑覆蓋反饋能力的灰盒測(cè)試系統(tǒng)ILS。表1更清晰展示 ILS和現(xiàn)有工作的方法差異,主要從是否具備路徑反饋能力、是否考慮JavaScript語(yǔ)法結(jié)構(gòu)特征、是否采用子樹(shù)覆蓋變異、是否考慮同類型子樹(shù)覆蓋操作、是否開(kāi)放工具源碼、是否自動(dòng)化程度較高這幾個(gè)方面進(jìn)行比較。
表1 ILS與現(xiàn)有相關(guān)工作的方法差異Table 1 The difference between ILS and existing JavaScript engine fuzzers
為了更直觀地展示 ILS在漏洞檢測(cè)能力上的提升,圖4和圖5給出了具體案例分析。如圖4,Jerryscript引擎暴露的 CVE-2018-11418和 CVE-2018-11419兩個(gè)緩存區(qū)溢出漏洞,二者的觸發(fā)漏洞樣本僅體現(xiàn)在RegExp函數(shù)中的參數(shù)有所不同,如果對(duì)CVE-2018-11418的漏洞觸發(fā)樣本中的參數(shù)部分進(jìn)行變異就能快速的觸發(fā)漏洞CVE-2018-11419。在后續(xù)的實(shí)際測(cè)試中,ILS通過(guò)同類型子樹(shù)覆蓋,提取CVE-2018-11418中的子樹(shù)信息,發(fā)現(xiàn)如圖5的兩個(gè)未知緩存區(qū)溢出漏洞bug-3870和bug-3871??梢园l(fā)現(xiàn),這兩個(gè)新漏洞樣本只替換了CVE-2018-11418樣本中RegExp函數(shù)的參數(shù),該參數(shù)內(nèi)容通過(guò)語(yǔ)法樹(shù)解析得到的是同一種子樹(shù)類型。
圖4 已知的Jerryscript漏洞Figure 4 Existing Jerryscript vulnerabilities
圖5 ILS新發(fā)現(xiàn)的漏洞Figure 5 New bugs found by ILS
本文所提出的ILS方法在AFL基礎(chǔ)上進(jìn)行擴(kuò)展,更改了AFL的變異策略。ILS使用一種基于子樹(shù)類型敏感的JavaScript引擎灰盒測(cè)試方法,降低了AFL在生成JavaScript代碼時(shí)的錯(cuò)誤概率,并具有更高的代碼覆蓋能力和漏洞發(fā)現(xiàn)能力。
AFL是谷歌開(kāi)發(fā)的標(biāo)桿性灰盒測(cè)試系統(tǒng),它的工作流程如圖6中的Execution所示,可以分為兩步:對(duì)目標(biāo)程序進(jìn)行插樁和對(duì)已插樁的程序進(jìn)行模糊測(cè)試。在插樁階段,AFL對(duì)目標(biāo)程序編譯時(shí),在每個(gè)基本塊插入一段代碼,用來(lái)記錄當(dāng)前基本塊和上一個(gè)基本塊的信息,主要代碼如下:
1 cur_location =
2 shared_mem[cur_location ^ prev_location]++;
3 prev_location = cur_location >> 1;
cur_location的值是隨機(jī)產(chǎn)生的,用來(lái)標(biāo)記當(dāng)前基本塊,shared_mem數(shù)組記錄上一個(gè)基本塊和當(dāng)前基本塊這條邊的命中次數(shù),如果命中次數(shù)的分類發(fā)生改變,則認(rèn)為產(chǎn)生了新的覆蓋率,prev_location表示上一個(gè)基本塊的標(biāo)記值,右移一位是為了區(qū)分基本塊的執(zhí)行順序。插樁完成后,AFL對(duì)已插樁的目標(biāo)程序進(jìn)行模糊測(cè)試,可以分為如下5個(gè)步驟:
1) 從輸入隊(duì)列(包括初始種子和產(chǎn)生新路徑的測(cè)試用例)中挑選出一個(gè)種子;
2) 保證覆蓋率不變的情況下減小種子的長(zhǎng)度;
3) 對(duì)種子進(jìn)行變異生成新的測(cè)試用例;
4) 執(zhí)行新的測(cè)試用例,并監(jiān)控目標(biāo)程序執(zhí)行狀態(tài);
5) 根據(jù)目標(biāo)程序執(zhí)行結(jié)果更新輸入隊(duì)列,然后轉(zhuǎn)到步驟1。
通過(guò)不斷循環(huán)上述5個(gè)步驟,AFL持續(xù)對(duì)目標(biāo)程序進(jìn)行測(cè)試,如果在步驟4中目標(biāo)程序發(fā)生崩潰,則記錄崩潰信息,并保存產(chǎn)生唯一崩潰的測(cè)試用例。
ILS的整體工作流程如圖6所示,可以分為初始種子預(yù)處理和運(yùn)行兩部分,圖中藍(lán)色框部分是 ILS在AFL基礎(chǔ)上增加的工作。ILS首先在初始種子預(yù)處理階段通過(guò)相關(guān)語(yǔ)法分析工具對(duì)初始種子進(jìn)行語(yǔ)法分析生成抽象語(yǔ)法樹(shù),然后對(duì)得到的抽象語(yǔ)法樹(shù)進(jìn)行類型識(shí)別和分類構(gòu)建相同類型子樹(shù)池,最后在變異階段對(duì)測(cè)試輸入增加語(yǔ)法分析,從同類型子樹(shù)池中隨機(jī)挑選出子樹(shù)進(jìn)行覆蓋變異。下面,本文詳細(xì)討論ILS方法的實(shí)現(xiàn)細(xì)節(jié)。
圖6 ILS工作流程Figure 6 The workflow of ILS
ILS對(duì)初始種子進(jìn)行語(yǔ)法分析得到抽象語(yǔ)法樹(shù),在語(yǔ)法樹(shù)層次對(duì)子樹(shù)進(jìn)行類型識(shí)別,并按類型分類構(gòu)建子樹(shù)池,詳細(xì)內(nèi)容如算法1所示。算法輸入為初始種子seeds和相關(guān)語(yǔ)法G。依次從seeds中選擇一個(gè)seed進(jìn)行解析,首先根據(jù)語(yǔ)法G將測(cè)試輸入in解析成抽象語(yǔ)法樹(shù)AST(第4行),解析過(guò)程中如果出現(xiàn)錯(cuò)誤,則說(shuō)明測(cè)試輸入in是和語(yǔ)法無(wú)關(guān)的,將其舍棄(第 5~7行)。如果成功解析得到抽象語(yǔ)法樹(shù)seed_ast,則依次訪問(wèn)語(yǔ)法樹(shù)的每個(gè)節(jié)點(diǎn),獲取節(jié)點(diǎn)的類型和內(nèi)容,并保存到typetree數(shù)據(jù)集合中(第8 ~12行),typetree是一個(gè)map容器,它的key為子樹(shù)的類型,value是一個(gè)set容器,保存子樹(shù)的內(nèi)容。對(duì)所有的初始種子解析完成后,可以得到所有子樹(shù)類型和子樹(shù)內(nèi)容集合typetree。根據(jù)typetree集合中每個(gè)類型的名字tree.id在數(shù)據(jù)庫(kù)中創(chuàng)建對(duì)應(yīng)的表,并在表中插入該類型的所有子樹(shù)tree[id]構(gòu)建同類型子樹(shù)池(第 14~17 行)。
算法1.初始種子預(yù)處理輸入: seeds: 初始種子,G: 相關(guān)語(yǔ)法1: type = ?2: typetree[id][text]= //id is the type name,?text is the set of subtree’s contexts 3: foreach seed in seeds do 4: parse seed into AST seed_ast according to G
5: if there are any parsing errors then 6: return 7: endif 8: ctx = VISIT(seed_ast) // ctx is the visiting node according to G 9: while ctx do 10: typetree[TYPEID(ctx)]= typetree[TYPEID(ctx)]∪ {GETTEXT(ctx)}11: VISITCHILDREN(ctx)12: endwhile 13: endfor 14: foreach tree in typetree do 15: CREATETABLE(tree.id)16: INSERTTABLE(tree[id])17: endfor
根據(jù)3.2節(jié)中得到的同類型子樹(shù)池,更改AFL的變異策略,使用同類型子樹(shù)覆蓋變異生成新的測(cè)試用例進(jìn)行模糊測(cè)試。算法2介紹了ILS同類型子樹(shù)變異過(guò)程,算法輸入為測(cè)試輸入in,相關(guān)語(yǔ)法G和同類型子樹(shù)池 typetree,輸出為新生成的測(cè)試用例集合T。首先使用語(yǔ)法G對(duì)測(cè)試輸入in進(jìn)行解析,解析過(guò)程和算法1解析相同(第3~6行)。解析完成后,依次訪問(wèn)抽象語(yǔ)法樹(shù)的每個(gè)節(jié)點(diǎn),獲取節(jié)點(diǎn)的類型和內(nèi)容,并保存到 subtree數(shù)據(jù)集合中,此步驟和算法 1中訪問(wèn)語(yǔ)法樹(shù)相同(第7 ~ 11行)。獲取語(yǔ)法樹(shù)所有節(jié)點(diǎn)類型和內(nèi)容信息后,對(duì)語(yǔ)法樹(shù)in_ast進(jìn)行替換變異,依次選擇子樹(shù)類型集合tree[id],并把in_ast中tree[id]類型的每個(gè)子樹(shù)s隨機(jī)替換為子樹(shù)池typetree[id]中同一類型的子樹(shù)typetree[id][random],生成新的測(cè)試用例ret,并保存到集合T中(第12~20行)。最后返回測(cè)試用例集合T(第21行)。
參考其他相關(guān)工作中對(duì)單個(gè)測(cè)試用例變異的次數(shù),本文選擇單個(gè)測(cè)試用例最大變異次數(shù)為10000。通過(guò) 10000除以這個(gè)測(cè)試用例中的子樹(shù)類型數(shù)目,再除以該類型子樹(shù)個(gè)數(shù)得到每個(gè)子樹(shù)的平均變異次數(shù)(第 14行),這樣保證測(cè)試用例中每個(gè)子樹(shù)都能被替換,并且保證每個(gè)子樹(shù)類型的總替換次數(shù)相同。
算法2.同類型子樹(shù)變異輸入: in: 測(cè)試輸入,G: 相關(guān)語(yǔ)法,typetree[id][text]: 同類型子樹(shù)池輸出: T: 新生成的的測(cè)試用例集合1: T= ?2: subtree[id][interval]= ? //id is the type
name,interval is the set of subtree’s location 3: parse in into AST in_ast according to G 4: if there are any parsing errors then 5: return 6: endif 7: ctx = VISIT(in_ast) // ctx is the visiting node according to G 8: while ctx do 9: subtree[TYPEID(ctx)]= subtree[TYPEID(ctx)]∪ { GETTEXT (ctx)}10: VISITCHILDREN(ctx)11: endwhile 12: foreach tree in subtree do 13: foreach s in tree[id]do 14: count = 10000/subtree.size()/tree[id].size()15: foreach i in count do 16: ret = replace s in in_ast’s copy with typetree[id][random()]17: T = T ∪ {ret}18: endfor 19: endfor 20: endfor 21: return T
以下本文用一個(gè)例子詳細(xì)介紹ILS的工作流程。使用圖7a作為算法1中的初始種子,圖7b作為算法2中的測(cè)試輸入。圖7a經(jīng)過(guò)語(yǔ)法解析得到圖8所示語(yǔ)法樹(shù),其中每一個(gè)非葉子節(jié)點(diǎn)和它的所有孩子節(jié)點(diǎn)表示一顆子樹(shù),該非葉子節(jié)點(diǎn)的類型表示了這顆子樹(shù)的類型。從 program根節(jié)點(diǎn)開(kāi)始訪問(wèn)該語(yǔ)法樹(shù),到
圖7 輸入種子和測(cè)試用例Figure 7 The original seed and test input
圖8 抽象語(yǔ)法樹(shù)ASTFigure 8 Abstract Syntax Tree
從表2中可以看到,在不同的類型中,可能它們的子樹(shù)是相同的,如圖4紅色框部分的子樹(shù) a(),它的類型有 FunctionBody、ExpressionSequence、ArgumentsExpression 3種。這增加了子樹(shù)類型的豐富性,在 ILS子樹(shù)變異過(guò)程中可以更有效的生成新的測(cè)試用例。
表2 圖7a通過(guò)語(yǔ)法分析得到的類型和內(nèi)容Table 2 The type and context obtained through syntax analysis from figure 7a
在同類型子樹(shù)替換變異階段,對(duì)圖7b通過(guò)語(yǔ)法分析得到表3。依次選擇表3中的Id的每個(gè)子樹(shù)替換為表2中相同Id的子樹(shù),可以得到3個(gè)新的測(cè)試用例,如下所示:在語(yǔ)法解析過(guò)程中還能得到 Program、SourceElements、Statement等類型的子樹(shù),第一個(gè)類型表示整顆語(yǔ)法樹(shù),進(jìn)行整個(gè)語(yǔ)法樹(shù)替換變異是沒(méi)有意義的,第二、三個(gè)類型表示的是這個(gè)子樹(shù)的源元素和狀態(tài),在整個(gè)語(yǔ)法樹(shù)中會(huì)多次出現(xiàn),但是并沒(méi)有實(shí)際意義,所以刪除這些無(wú)用的類型,只保留具有一定意義的子樹(shù)類型,如表2中一共得到10種不同有意義的類型。
表3 圖7b通過(guò)語(yǔ)法分析得到的類型和內(nèi)容Table 3 The type and context obtained through syntax analysis from figure 7b
和ILS相比,Superion的子樹(shù)替換策略是無(wú)類型的,這樣在替換的時(shí)候會(huì)造成很多錯(cuò)誤,如圖7b中的數(shù)字1被圖7a中的a()替換,生成var a = a(),會(huì)造成TypeError。但是ILS同類型子樹(shù)替換策略就會(huì)減少這類問(wèn)題,Literal類型的數(shù)字1只能被表2中同類型的true子樹(shù)替換,生成新的測(cè)試用例var a = true,可以順利被解析引擎運(yùn)行。
本文在AFL基礎(chǔ)上,使用C/C++語(yǔ)言實(shí)現(xiàn)子樹(shù)類型敏感的灰盒模糊測(cè)試系統(tǒng) ILS。該系統(tǒng)使用ANTLR 4[54]作為語(yǔ)法分析工具對(duì)初始種子進(jìn)行詞法分析和語(yǔ)法分析,獲取初始種子的類型和子樹(shù)構(gòu)建同類型子樹(shù)池,在子樹(shù)變異階段,使用ANTLR 4對(duì)測(cè)試輸入進(jìn)行詞法分析和語(yǔ)法分析,隨機(jī)從子樹(shù)池中挑選同類型的子樹(shù)替換測(cè)試輸入中的每個(gè)子樹(shù)生成新的測(cè)試用例。
該系統(tǒng)充分利用了 AFL的優(yōu)勢(shì),能夠?qū)δ繕?biāo)進(jìn)行快速測(cè)試,并通過(guò)覆蓋率反饋,提高對(duì)目標(biāo)的代碼覆蓋率,增加發(fā)現(xiàn)漏洞的概率。而且該系統(tǒng)容易擴(kuò)展,擴(kuò)展相關(guān)的語(yǔ)法可以對(duì)其他結(jié)構(gòu)化語(yǔ)法輸入對(duì)象(如XML解析器)進(jìn)行測(cè)試。
為了驗(yàn)證 ILS的有效性,本文將此模型與Superion和CodeAlchemist進(jìn)行實(shí)驗(yàn)對(duì)比,在表1所列出的開(kāi)源工具中,Superion是基于子樹(shù)變異的模糊測(cè)試方法中的典型工具,在相關(guān)JavaScript引擎中發(fā)現(xiàn)了23個(gè)未知的Bug,CodeAlchemist是基于生成的模糊測(cè)試方法中的典型工具,在相關(guān)JavaScript引擎中發(fā)現(xiàn)了11個(gè)未知的Bug。本文與這兩個(gè)工具進(jìn)行實(shí)驗(yàn)對(duì)比,可以體現(xiàn)出ILS方法的先進(jìn)性。
本文分別從漏洞發(fā)現(xiàn)能力、代碼覆蓋能力、測(cè)試?yán)行省?zhí)行速度4個(gè)方面進(jìn)行性能對(duì)比: 漏洞發(fā)現(xiàn)能力最能體現(xiàn)出工具的有效性; 代碼覆蓋能力是衡量測(cè)試結(jié)果好壞的基本標(biāo)準(zhǔn),能夠整體上體現(xiàn)出模糊測(cè)試工具的效果; 生成測(cè)試用例有效性對(duì)于JavaScript引擎的模糊測(cè)試來(lái)說(shuō)尤其重要,一般隨機(jī)變異產(chǎn)生的測(cè)試用例都不能被JavaScript引擎解析運(yùn)行; 執(zhí)行速度是模糊測(cè)試工具中重要的一環(huán),表示時(shí)間效率。
本文選擇三個(gè)開(kāi)源的JavaScript引擎JerryScript、ChakraCore和 JavaScriptCore作為測(cè)試對(duì)象,JerryScript版本為2.2.0,ChakraCore版本為1.12.0.0-beta,JavaScriptCore版本為2.27.4。JerryScript是三星集團(tuán)開(kāi)發(fā)的輕量級(jí)物聯(lián)網(wǎng)JavaScript引擎,適用于嵌入式設(shè)備,只需要很低的CPU的性能和內(nèi)存空間。ChakraCore是 Microsoft Edge瀏覽器中 Chakra JavaScript引擎的核心部分。JavaScriptCore是WebKit瀏覽器的JavaScript解析引擎部分,WebKit是一個(gè)跨平臺(tái)的瀏覽器引擎,它支持 Safari、iBook和 App Store,以及各種Mac系統(tǒng),iOS和Linux平臺(tái)。
為了平衡實(shí)驗(yàn)的系統(tǒng)資源開(kāi)銷,本文對(duì)這 3個(gè)模糊測(cè)試工具都只使用 4個(gè)并行進(jìn)程進(jìn)行實(shí)驗(yàn),保證同時(shí)運(yùn)行4個(gè)JavaScript引擎,在一定程度上體現(xiàn)系統(tǒng)資源的公平性。
在測(cè)試用例方面,對(duì) JerryScript引擎收集了1698個(gè)測(cè)試用例,對(duì)ChakraCore引擎收集了1766個(gè)測(cè)試用例,對(duì)JavaScriptCore引擎收集了2713個(gè)測(cè)試用例。
實(shí)驗(yàn)中所用機(jī)器為帶有 64G內(nèi)存的 Dell PowerEdge R740,操作系統(tǒng)為64位的Ubuntu 18.04。本文參考其他相關(guān)工作的測(cè)試時(shí)間,一般測(cè)試時(shí)間為24 h,所以本文也對(duì)JavaScript引擎測(cè)試24 h。由于模糊測(cè)試具有隨機(jī)性,所以重復(fù)進(jìn)行 10次實(shí)驗(yàn),對(duì)代碼覆蓋率、測(cè)試?yán)行?、?zhí)行速度取平均值進(jìn)行對(duì)比,并對(duì)比10次實(shí)驗(yàn)的漏洞發(fā)現(xiàn)總數(shù)。
重復(fù)進(jìn)行10次24 h實(shí)驗(yàn)后,Bug發(fā)現(xiàn)情況如表4所示。在Bug發(fā)現(xiàn)率方面,ILS相比于Superion提升了100%。CodeAlchemist并不支持對(duì)JerryScript引擎進(jìn)行測(cè)試,而且在ChakraCore和JavaScriptCore引擎中都沒(méi)有發(fā)現(xiàn)Bug。表5詳細(xì)列出了截止本文寫(xiě)作時(shí)間,ILS發(fā)現(xiàn)的所有Bug具體信息,共發(fā)現(xiàn)26個(gè)不同的Bug。在JerryScript引擎中,共發(fā)現(xiàn)22個(gè)Bug,包括1個(gè)Use-After-Free、3個(gè)Buffer Overflow、2個(gè)Stack Overflow、1個(gè) Memory Corruption和 15個(gè)Assertion Failure。在ChakraCore引擎中,一共發(fā)現(xiàn)3個(gè)Assertion Failure。在JavaScriptCore引擎中,一共發(fā)現(xiàn)1個(gè) Memory Corruption。由于CodeAlchemist并沒(méi)有發(fā)現(xiàn)Bug,所以沒(méi)有放入表5中進(jìn)行對(duì)比。
表4 24 h Bug發(fā)現(xiàn)情況對(duì)比Table 4 The comparison of Bug discovery in 24 hours
表5 ILS發(fā)現(xiàn)的BugTable 5 The Bugs found by ILS
① https://github.com/jerryscript-project/jerryscript/issues/created_by/owl337
② https://github.com/microsoft/ChakraCore/issues/created_by/owl337
③ https://bugs.webkit.org/show_bug.cgi?id=212460
在模糊測(cè)試中,代碼覆蓋率是衡量測(cè)試結(jié)果好壞的基本標(biāo)準(zhǔn),能夠整體上體現(xiàn)出模糊測(cè)試工具的效果,代碼覆蓋率越高,越有可能發(fā)現(xiàn)新的Bug。
本文分別對(duì)JerryScript和JavaScriptCore進(jìn)行了覆蓋率對(duì)比實(shí)驗(yàn),并使用 afl-cov[55]收集覆蓋率信息,結(jié)果表明ILS、Superion和CodeAlchemist對(duì)代碼行覆蓋率和函數(shù)覆蓋率都有提升,ILS提升效果更好。因?yàn)镃odeAlchemist不支持測(cè)試JerryScript解析引擎,所以沒(méi)有進(jìn)行JerryScript解析引擎的覆蓋率對(duì)比。
對(duì)于JerryScript,實(shí)驗(yàn)結(jié)果如圖9所示。在代碼行覆蓋率方面,ILS相比于Superion提升48%,在函數(shù)覆蓋率方面,ILS相比于Superion提升41%。
圖9 JerryScript引擎覆蓋率對(duì)比Figure 9 The comparison coverage rate of JerryScript
對(duì)于JavaScriptCore,實(shí)驗(yàn)結(jié)果如圖10所示。在代碼行覆蓋率上,ILS相比Superion提升了72%,相比CodeAlchemist提升48%; 在函數(shù)覆蓋率上,ILS相比Superion提升80%,相比CodeAlchemist提升58%。
圖10 JavaScriptCore引擎覆蓋率對(duì)比Figure 10 The comparison coverage rate of JavaScriptCore
生成測(cè)試用例有效性對(duì)于JavaScript引擎的模糊測(cè)試來(lái)說(shuō)非常重要,一般的模糊測(cè)試工具如 AFL,隨機(jī)變異產(chǎn)生的測(cè)試用例基本上都是無(wú)效的,因?yàn)槿绻环蠈?duì)應(yīng)的語(yǔ)法規(guī)則,解析引擎將拒絕繼續(xù)執(zhí)行,所以很難發(fā)現(xiàn)系統(tǒng)運(yùn)行時(shí)的Bug。
圖11顯示了生成測(cè)試用例錯(cuò)誤率的實(shí)驗(yàn)結(jié)果,ILS、Superion和 CodeAlchemist的平均錯(cuò)誤率分別是46.16%,58.74%和72.49%。因?yàn)镮LS在替換子樹(shù)時(shí)沒(méi)有對(duì)子樹(shù)的引用進(jìn)行檢查,所以 ILS的ReferenceError錯(cuò)誤是最多的,但是ILS能有效的減少其他的錯(cuò)誤率,種子測(cè)試有效率比 Superion提升了36%,比CodeAlchemist提升了21%。
圖11 生成種子錯(cuò)誤率對(duì)比Figure 11 The error Comparison of new seeds
執(zhí)行速率表示單位時(shí)間內(nèi)調(diào)用目標(biāo)軟件運(yùn)行的次數(shù),執(zhí)行速度越快,越有可能在短時(shí)間內(nèi)發(fā)現(xiàn)新的Bug。
本文統(tǒng)計(jì)10次實(shí)驗(yàn)每個(gè)工具生成的測(cè)試用例個(gè)數(shù),并平均計(jì)算得到每個(gè)JavaScript引擎每秒運(yùn)行次數(shù),結(jié)果如表6所示。由于ILS和Superion都是基于AFL開(kāi)發(fā)的,具有AFL的forkserver模式加速,所以執(zhí)行速度快,CodeAlchemist是自己控制JavaScript引擎執(zhí)行,并沒(méi)有對(duì)執(zhí)行速度進(jìn)行優(yōu)化,所以性能較低。在 JerryScript引擎中,平均執(zhí)行速率 ILS比Superion每秒降低了3.03次; 在Chakracore引擎中,平均執(zhí)行速率ILS比Superion每秒降低了1.01次; 在JavaScriptCore引擎中,整體平均執(zhí)行速率 ILS比Superion每秒降低了2.6次。
表6 每秒執(zhí)行速率對(duì)比Table 6 The execution rate pre second comparison
ILS執(zhí)行速率比Superion有所降低。但總體來(lái)說(shuō)相差不大,在覆蓋率提升顯著的情況下,這個(gè)執(zhí)行速率的差異是可以接受的。
本文詳細(xì)分析了針對(duì)JavaScript引擎的模糊測(cè)試技術(shù),并在路徑反饋的模糊測(cè)試框架基礎(chǔ)上提出一種基于子樹(shù)類型敏感的JavaScript引擎灰盒測(cè)試方法ILS。該方法通過(guò)對(duì)JavaScript代碼進(jìn)行語(yǔ)法分析,把子樹(shù)進(jìn)行識(shí)別分類,并在變異過(guò)程中使用同類型子樹(shù)進(jìn)行替換變異。實(shí)驗(yàn)結(jié)果表明,該方法能顯著提升生成測(cè)試用例的有效率,并具有更高的代碼覆蓋能力,而且發(fā)現(xiàn)了26個(gè)新的Bug。
ILS在下一步工作中,將結(jié)合基于生成的模糊測(cè)試技術(shù),對(duì)JavaScript代碼進(jìn)行更細(xì)粒度的控制流分析和數(shù)據(jù)流分析,在子樹(shù)替換變異過(guò)程中消除引用未知變量,進(jìn)一步消除引用錯(cuò)誤以提升代碼生成的有效率。