程 亮, 王化磊, 張 陽, 孫曉山
1(中國科學(xué)院大學(xué), 北京 100049)
2(中國科學(xué)院 軟件研究所 可信計(jì)算與信息保障實(shí)驗(yàn)室, 北京 100190)
隨著計(jì)算機(jī)和網(wǎng)絡(luò)技術(shù)的發(fā)展, 軟件與我們的生活和工作的關(guān)系越來越密切. 然而軟件復(fù)雜的功能使得軟件中不可避免地存在漏洞. 在模糊測試首次被提出的論文[1]中提到“常用系統(tǒng)中可能會(huì)潛伏著嚴(yán)重的漏洞”. 比如: 2010年披露的震網(wǎng)蠕蟲漏洞[2]是第一種攻擊工業(yè)控制系統(tǒng)的病毒; 2015年6月, 三星被爆出了高危的輸入法漏洞. 該漏洞影響全球超過6億的三星手機(jī)用戶[3]. 2015年7月Android被爆出存在Stagefright高危漏洞, 約95%的安卓設(shè)備受到該漏洞影響[3].2020年8月, 研究人員發(fā)現(xiàn)CSP繞過漏洞(CVE-2020-6519[4]), 該漏洞使攻擊者可以完全繞過Chrome 73版至83版的CSP規(guī)則, 數(shù)十億的用戶可能會(huì)受到影響.
軟件安全一直是安全人員研究的重點(diǎn), 當(dāng)前主流的程序安全分析方法有: 污點(diǎn)分析、符號(hào)執(zhí)行、代碼審計(jì)和模糊測試等. 如何高效地發(fā)掘軟件可能存在的漏洞一直是這些主流安全分析方法研究的重點(diǎn).
污點(diǎn)分析技術(shù)[5]可以分為動(dòng)態(tài)污點(diǎn)分析和靜態(tài)污點(diǎn)分析, 靜態(tài)污點(diǎn)在無法獲取源代碼時(shí), 靜態(tài)污點(diǎn)分析的精確性將會(huì)大大降低. 動(dòng)態(tài)污點(diǎn)分析在運(yùn)行時(shí)具有很大的開銷, 難以實(shí)際分析規(guī)模較大的軟件. 符號(hào)執(zhí)行系統(tǒng)地探索許多可能的執(zhí)行路徑, 而不需要具體的輸入, 通過抽象地將輸入表示為符號(hào), 利用約束求解器來構(gòu)造可能滿足條件的輸入. 符號(hào)執(zhí)行的缺點(diǎn)是處理像循環(huán)這樣的語言結(jié)構(gòu)時(shí)可能會(huì)成倍地增加執(zhí)行狀態(tài)的數(shù)量, 從而出現(xiàn)路徑爆炸的問題[6-8]. 代碼審計(jì)是一種對(duì)源代碼的全面分析技術(shù), 但是代碼審計(jì)非常依賴安全人員自身的經(jīng)驗(yàn). 綜上分析, 符號(hào)執(zhí)行等方法雖然通過提取豐富的代碼細(xì)節(jié)達(dá)到程序分析的功能, 但是由于其效率等方面的原因, 在程序安全性分析方面存在較多的局限. 模糊測試[9]通過隨機(jī)變異種子或者基于規(guī)則生成種子對(duì)程序進(jìn)行測試. 模糊測試通常分為白盒模糊測試、灰盒模糊測試和黑盒模糊測試[10-13]. 白盒模糊測試提取程序詳細(xì)的運(yùn)行時(shí)信息, 但是開銷很大,總體效率很低. 黑盒模糊測試完全忽略了程序的內(nèi)在信息, 雖然具有較快的運(yùn)行速度, 但是準(zhǔn)確性很低, 總體漏洞發(fā)現(xiàn)能力較弱. 而灰盒模糊測試兼顧了兩者的優(yōu)勢, 通過靜態(tài)代碼插樁的方式獲取程序運(yùn)行時(shí)覆蓋情況, 并用獲得的信息指導(dǎo)種子變異方式, 以盡快擴(kuò)大測試的覆蓋率, 相較于其他方法能夠更快地發(fā)現(xiàn)程序潛在的漏洞. 因此, 灰盒模糊測試已成為目前主流的模糊測試方法, 其中典型工具—AFL (American fuzzy loop)[14]已成為學(xué)術(shù)界和工業(yè)界進(jìn)行模糊測試的事實(shí)標(biāo)準(zhǔn)工具, 我們的工作也基于AFL實(shí)現(xiàn).
雖然灰盒模糊測試在發(fā)現(xiàn)漏洞方面具有一定的優(yōu)勢. 但是其采用的隨機(jī)性算法具有極大的盲目性, 所以仍然存在進(jìn)一步改進(jìn)的空間.
現(xiàn)有的針對(duì)基于AFL灰盒模糊測試的改進(jìn)工具將全部或過多的能量集中非確定性變異階段, 加大了變異的盲目性, 使其難以求解復(fù)雜的條件約束;并且在種子能量分配階段忽視了種子探索新分支的能力, 使得過多的能量消耗在沒有價(jià)值的種子.
針對(duì)上述問題, 我們?cè)谀:郎y試工具AFL 2.52b進(jìn)行了改進(jìn), 通過對(duì)關(guān)鍵變異位置持續(xù)性變異和能量分配策略的優(yōu)化, 提高模糊測試發(fā)現(xiàn)程序覆蓋和程序潛在漏洞的能力, 我們的設(shè)計(jì)有以下幾個(gè)特點(diǎn):
1)提取有效變異位置. 在種子變異階段, 首先對(duì)種子執(zhí)行非確定性變異. 對(duì)于產(chǎn)生新覆蓋的非確定性變異種子, 我們提取變異的組合位置并認(rèn)為該組合位置中存在有效變異位置(我們定義變異后能夠產(chǎn)生有效新覆蓋的單一位置是有效變異位置), 再利用聚類算法確定組合變異中有效變異位置, 最后針對(duì)有效變異位置以及其后續(xù)位置進(jìn)行持續(xù)的細(xì)粒度變異.
2)利用新覆蓋信息評(píng)估種子. 對(duì)于每個(gè)發(fā)現(xiàn)新覆蓋的種子, 保留新發(fā)現(xiàn)覆蓋的信息. 在種子評(píng)分階段,根據(jù)種子的新覆蓋信息對(duì)種子進(jìn)行評(píng)分.
3)提取程序靜態(tài)信息. 模糊測試改進(jìn)往往是在缺少程序信息的前提下進(jìn)行的策略上的優(yōu)化, 這種優(yōu)化存在局限性; 而使用污點(diǎn)分析或者符號(hào)執(zhí)行等方式提取程序信息的方法[15-18], 往往因?yàn)榉治鲂瘦^低而影響模糊測試工具總體的效率. 因此我們提取了輕量級(jí)的程序靜態(tài)信息, 在模糊測試階段結(jié)合靜態(tài)信息對(duì)種子的能量分配策略進(jìn)行更加準(zhǔn)確的計(jì)算.
我們?cè)谥髁鞯哪:郎y試工具AFL的設(shè)計(jì)思路上完成了改進(jìn), 并實(shí)現(xiàn)了改進(jìn)后的模糊測試工具AgileFuzz經(jīng)過實(shí)驗(yàn)驗(yàn)證, AgileFuzz能夠在相同的時(shí)間內(nèi)發(fā)現(xiàn)更多的程序分支覆蓋, 并且能夠挖掘到新的程序漏洞.
本節(jié)主要以AFL為例介紹典型灰盒模糊測試的工作流程以及路徑統(tǒng)計(jì)方式.
AFL主函數(shù)是一個(gè)條件為true的while循環(huán), 只有用戶主動(dòng)停止模糊測試工作, 測試才會(huì)結(jié)束. AFL的工作流程如圖1所示, 核心步驟如下: 1)待測目標(biāo)程序和程序的輸入文件作為AFL啟動(dòng)時(shí)的原始輸入, 初始輸入經(jīng)過運(yùn)行后會(huì)加入種子庫中參與后續(xù)的模糊測試. 2) AFL每次執(zhí)行測試, 都會(huì)從種子隊(duì)列中選擇1個(gè)種子, 根據(jù)該種子的執(zhí)行時(shí)間、種子大小、路徑覆蓋數(shù)量、執(zhí)行次數(shù)等進(jìn)行種子評(píng)分, 評(píng)分越高的種子在非確定性變異階段會(huì)進(jìn)行更多次的變異. 并且, AFL根據(jù)路徑不同保存了很多種子, 但是AFL會(huì)將單一分支執(zhí)行最快的種子標(biāo)記為favored, 在種子被選擇后, 不是favored標(biāo)記的種子會(huì)以較大的概率跳過執(zhí)行. 3)種子經(jīng)過變異后, 得到的新種子作為待測程序的輸入,AFL監(jiān)視每個(gè)種子執(zhí)行過程中程序是否發(fā)生崩潰, 如果待測程序發(fā)生崩潰, 則種子被保存在crash種子隊(duì)列. 4) AFL還記錄每個(gè)種子在程序執(zhí)行過程中的路徑覆蓋情況, 如果產(chǎn)生新的覆蓋則將種子加入正常樣本隊(duì)列, 然后參與后續(xù)的模糊測試工作.
圖1 AFL工作流程圖
AFL通過插樁方式獲取程序運(yùn)行時(shí)的執(zhí)行路徑信息. 對(duì)于有源碼的程序, AFL在編譯程序時(shí)將插樁代碼插入程序的每個(gè)基本塊中, 具體流程如下: AFL在每個(gè)基本塊入口處插入0-65535范圍的隨機(jī)數(shù)以及特定功能的函數(shù)afl_maybe_log;如果程序執(zhí)行了該基本塊,afl_maybe_log函數(shù)會(huì)將插入基本塊的隨機(jī)數(shù)與前一個(gè)執(zhí)行的基本塊的隨機(jī)數(shù)進(jìn)行異或操作, 運(yùn)算的結(jié)果作為覆蓋信息寫入共享內(nèi)存. 共享內(nèi)存是一塊64 KB的內(nèi)存空間, 可以統(tǒng)計(jì)65 536條分支轉(zhuǎn)移信息, AFL不僅記錄分支轉(zhuǎn)移是否發(fā)生, 還會(huì)記錄分支轉(zhuǎn)移執(zhí)行的次數(shù), 因?yàn)橥粋€(gè)分支轉(zhuǎn)移, 可能因?yàn)椴煌膱?zhí)行次數(shù)出現(xiàn)不用的程序狀態(tài). 對(duì)于沒有源碼的程序, AFL使用運(yùn)行時(shí)插樁技術(shù)統(tǒng)計(jì)程序執(zhí)行路徑, 插樁的邏輯與靜態(tài)插樁方式相同.
如圖2所示, 其中實(shí)線方框?yàn)锳FL的標(biāo)準(zhǔn)功能模塊, 使用虛線方框的部分是我們?cè)黾踊蚋倪M(jìn)的模塊, 主要包括3個(gè)部分: 第1部分是對(duì)模糊測試變異策略的改進(jìn), 第2部分是利用聚類算法確定關(guān)鍵變異位置, 第3部分是結(jié)合靜態(tài)分析和新覆蓋信息的種子評(píng)分策略調(diào)整.
圖2 改進(jìn)后的模糊測試工作流程
AFL在種子變異階段分為確定性變異和非確定性變異. 每個(gè)被選中的種子都會(huì)執(zhí)行一次確定性變異, 在確定性變異階段會(huì)對(duì)種子進(jìn)行比特位粒度的變異, 所以在確定性變異階段十分耗時(shí). 事實(shí)上, 種子的很多位置都是無效的變異位置, 即無論進(jìn)行何種變異都無法產(chǎn)生新的覆蓋. MOPT和EcoFuzz考慮到確定性變異耗時(shí), 所以選擇直接跳過了確定性變異, 但是只通過非確定性變異, 將會(huì)使得模糊測試變異更加盲目和隨機(jī).
(1) 確定種子關(guān)鍵變異位置. 在調(diào)整后的變異策略中, 種子變異階段只對(duì)種子的部分關(guān)鍵位置進(jìn)行確定性變異. 核心步驟是確定種子的關(guān)鍵位置. 具體來說,當(dāng)選中一個(gè)種子后, 首先進(jìn)行非確定性變異, 如果非確定性變異生成的種子訪問了新的分支覆蓋, 并不會(huì)在保存種子后直接進(jìn)行下一次變異操作, 而是分析產(chǎn)生該種子的變異過程. 通過分析, 可以確定組合變異位置中有效的變異位置, 而有效的變異位置將會(huì)記作新種子的關(guān)鍵位置.
(2) 選擇性確定性變異. 在確定關(guān)鍵位置w后, 變異前的種子和變異后的種子會(huì)針對(duì)關(guān)鍵位置進(jìn)行不同的變異操作. 對(duì)變異前的種子的w位置進(jìn)行與AFL相同的確定性變異, 對(duì)于記錄關(guān)鍵位置的新種子, 如果關(guān)鍵位置的字段長度小于m個(gè)字節(jié), 那么當(dāng)該種子被選中進(jìn)行變異時(shí), 首先對(duì)該關(guān)鍵位置的后續(xù)n個(gè)位置進(jìn)行更加細(xì)粒度的確定性變異, 與AFL原有的確定性變異不同, 細(xì)粒度的確定性變異會(huì)將選中的位置(字節(jié))變異成所有可能的結(jié)果. 經(jīng)過多次實(shí)驗(yàn)測試, m和n的值取2時(shí), 總體效果較好.
關(guān)鍵位置的長度直接影響變異的效率. 如果將產(chǎn)生新覆蓋的種子變異過程中的所有組合變異位置都看作關(guān)鍵位置, 然后對(duì)這些進(jìn)行確定性變異, 仍然存在較多的無效變異.
為了縮小關(guān)鍵位置的長度, 使用聚類算法對(duì)離散的組合變異位置進(jìn)行聚類. 在文件結(jié)構(gòu)中, 字段是連續(xù)的一段內(nèi)容, 所以在一個(gè)文件中, 距離越近的位置越可能屬于同一字段. 如圖3所示, 文件A的組合變異M個(gè)位置(其中包括藍(lán)色標(biāo)記和紅色位置標(biāo)記的位置,而且紅色位置為關(guān)鍵變異位置)得到的種子B訪問了新的覆蓋, 對(duì)種子B變異的位置進(jìn)行聚類操作-將離散的變異位置聚類為N個(gè)字段, 根據(jù)N個(gè)字段生成N個(gè)新的種子, 每個(gè)新種子只有對(duì)應(yīng)字段的內(nèi)容與原文件不同. 如果種子Ni訪問了新的覆蓋, 那么Ni種子對(duì)應(yīng)的變異字段就是關(guān)鍵的變異字段.
圖3 對(duì)組合變異位置進(jìn)行聚類
為了完成變異位置聚類, 我們使用Meanshift算法.使用該算法的原因有兩點(diǎn): 1)該算法是基于密度的聚類算法, 2)聚類之前不需要指定類的數(shù)量. Meanshift算法的核心思想是通過不斷移動(dòng)樣本點(diǎn), 使其向密度更大的區(qū)域移動(dòng), 直到滿足某一條件, 此時(shí)該點(diǎn)就是樣本點(diǎn)的收斂點(diǎn), 收斂到同一點(diǎn)則被認(rèn)為屬于同一族類.對(duì)于變異位置p, 其偏移向量計(jì)算方式如式(1)所示,其中, pi表示所有變異位置點(diǎn)集中到p點(diǎn)距離小于l的所有點(diǎn).
聚類算法具體步驟如下:
1)隨機(jī)選擇未被分類的變異位置, 作為中心點(diǎn)P.
2)找出離中心點(diǎn)P距離L范圍的所有變異點(diǎn), 這些點(diǎn)記作集合M.
3)計(jì)算中心點(diǎn)P與集合M中所有點(diǎn)的向量, 將這些向量相加得到偏移向量M.
4)將中心點(diǎn)P加上向量M得到新的中心點(diǎn).
5)重復(fù)步驟2)-4), 直到偏移向量滿足設(shè)定的閾值,保存此時(shí)的中心點(diǎn).
6)重復(fù)步驟1)-5)直到所有點(diǎn)都完成分類.
7)根據(jù)每個(gè)類, 對(duì)每個(gè)點(diǎn)的訪問頻率, 取訪問頻率最大的那個(gè)類, 作為當(dāng)前點(diǎn)集的所屬類.
算法1. 基于聚類的確定性變異優(yōu)化方法輸入: 非確定性變異后產(chǎn)生新覆蓋的種子seed_son和變異前的種子seed輸出: 確定性變異產(chǎn)生的新覆蓋的種子1 diff_points=get_diff_point(seed, seed_son)2 cluster_points=cluster(diff_ponts)3 for cluster in cluster_points:4 seed_single_cluster=generate_seed_by_cluster(cluster):5 if(is_new_path(seed_single)):6 seeds_deter=deter_variate(cluster, seed):7 while seed_deter in seeds_deter:8 fuzzy_run(seed_deter)9 end while 10 end if 11 end for
在AFL的種子評(píng)分中, 會(huì)根據(jù)種子的總分支覆蓋數(shù)量進(jìn)行能量分配, 這種方式導(dǎo)致能量分配不合理. 我們調(diào)整種子評(píng)分策略, 將種子新發(fā)現(xiàn)的分支數(shù)量作為評(píng)分依據(jù). 并且我們對(duì)待測二進(jìn)制程序進(jìn)行靜態(tài)分析,提取基本塊轉(zhuǎn)移信息. 這樣做的目的是因?yàn)椴⒉皇敲總€(gè)分支轉(zhuǎn)移都存在潛在未發(fā)現(xiàn)的分支轉(zhuǎn)移.
如圖4所示, 對(duì)于每個(gè)基本塊轉(zhuǎn)移, 如: branch 1,我們記錄通過該分支轉(zhuǎn)移到達(dá)基本塊后, 可能存在的后續(xù)基本塊轉(zhuǎn)移, 即對(duì)于branch 1, 我們記錄branch 1-1和branch 1-2的信息, 我們把branch 1-1和branch 1-2記作分支branch 1的子分支轉(zhuǎn)移. 注意的是, 雖然基本塊是連續(xù)指令的集合, 但是branch 1-1或branch 1-2可能并不同時(shí)存在或都不存在. 這種情況發(fā)生在某基本塊子節(jié)點(diǎn)的父節(jié)點(diǎn)超過一個(gè)時(shí), 其子節(jié)點(diǎn)即使只有一個(gè), 但是仍然是一個(gè)獨(dú)立的基本塊. 通過靜態(tài)分析, 我們可以得到每個(gè)基本塊轉(zhuǎn)移的子分支轉(zhuǎn)移, 如果某個(gè)分支的子分支轉(zhuǎn)移數(shù)量為2, 我們認(rèn)為該分支轉(zhuǎn)移對(duì)發(fā)現(xiàn)新覆蓋是有價(jià)值的, 將會(huì)對(duì)種子評(píng)分產(chǎn)生增益效果.
圖4 基本塊轉(zhuǎn)移示意圖
所以在種子評(píng)分階段, 具體步驟如下:
1) 對(duì)于待測程序, 通過靜態(tài)分析獲取每個(gè)基本塊轉(zhuǎn)移的子分支轉(zhuǎn)移信息, 保存在文件中, 在啟動(dòng)模糊測試測試時(shí), 該文件作為分支附加信息提供.
2) 對(duì)于每個(gè)新加入隊(duì)列的種子, 比較其分支覆蓋與總分支覆蓋的差異, 得到新發(fā)現(xiàn)的分支覆蓋數(shù)量和具體分支編號(hào).
3) 在種子評(píng)分階段, 計(jì)算種子分支覆蓋中是新覆蓋且對(duì)應(yīng)分支有兩個(gè)子分支的數(shù)量, 記作value_branch_num.
4) 種子A的評(píng)分使用式(2)進(jìn)行計(jì)算, 使用log函數(shù)是為了避免分支覆蓋數(shù)量對(duì)種子能量進(jìn)行成倍的增益, 并且經(jīng)過多次實(shí)驗(yàn)驗(yàn)證, ln函數(shù)作為計(jì)算種子能量總體實(shí)驗(yàn)效果較好. 根據(jù)公式可知, 當(dāng)種子的新覆蓋數(shù)量為0時(shí), 最低能量值為1.
我們?cè)贏FL 2.52b的基礎(chǔ)上實(shí)現(xiàn)了改進(jìn)策略, 得到了改進(jìn)后的模糊測試工具AgileFuzz. 我們的評(píng)估主要回答下面4個(gè)問題:
1) 產(chǎn)生新覆蓋的非確定性變異的組合位置中是否存在關(guān)鍵位置? 如果存在, 存在的比例是多少? 對(duì)關(guān)鍵位置進(jìn)行確定性變異, 是否能夠發(fā)現(xiàn)新的覆蓋?
2) 與非確定性變異相比, 對(duì)聚類得到關(guān)鍵位置進(jìn)行細(xì)粒度持續(xù)變異如何能夠更快地發(fā)現(xiàn)新覆蓋?
3) AgileFuzz在實(shí)際程序中發(fā)現(xiàn)程序覆蓋的能力與現(xiàn)有的模糊測試改進(jìn)工具對(duì)比如何?
4) AgileFuzz是否能夠發(fā)現(xiàn)真實(shí)程序程序中的漏洞?
非確定性變異階段對(duì)種子的隨機(jī)組合位置進(jìn)行變異, 變異后的種子產(chǎn)生新覆蓋可能有兩個(gè)原因: 1)組合變異產(chǎn)生新覆蓋, 單一位置變異并不能產(chǎn)生; 2)組合變異中, 變異了“關(guān)鍵位置”, 而且即使只變異該位置, 也可以產(chǎn)生新覆蓋. 其中, 我們稱這種“關(guān)鍵位置”為單一有效變異位置. 我們統(tǒng)計(jì)在模糊測試過程中, 產(chǎn)生新覆蓋的非確定性變異包括多少“關(guān)鍵位置”以及針對(duì)“關(guān)鍵位置”變異仍然能夠產(chǎn)生新覆蓋的數(shù)量. 實(shí)驗(yàn)測試選擇libxml2 (xmllint)、binutils (readelf)和harfbuzz(test)這3組程序, 這3組程序常用作模糊測試工具的測評(píng), 比較具有代表性. 在相同的實(shí)驗(yàn)環(huán)境下, 對(duì)3個(gè)程序進(jìn)行3組重復(fù)性實(shí)驗(yàn), 每組實(shí)驗(yàn)進(jìn)行72 h, 最終取平均結(jié)果. 統(tǒng)計(jì)結(jié)果如表1所示, 從結(jié)果中可以看出, 產(chǎn)生新覆蓋的非確定性變異次數(shù)中, 具有“關(guān)鍵位置”的非確定性變異比例較高(分別為59%、45%和36%), 并且90%以上的“關(guān)鍵位置”經(jīng)過確定性變異后仍然能夠產(chǎn)生新覆蓋.
在本小節(jié), 我們解釋為什么針對(duì)“關(guān)鍵位置”進(jìn)行細(xì)粒度變異相比非確定性變異能夠更快地發(fā)現(xiàn)新覆蓋.我們以libxml2的xmllint程序?yàn)槔? 將我們的模糊測試工具AgileFuzz與AFL 2.52b、關(guān)閉確定性變異的AFL 2.52b -d以及關(guān)閉確定性變異的模糊測試改進(jìn)工具EcoFuzz進(jìn)行24 h實(shí)驗(yàn)比較, 覆蓋率對(duì)比結(jié)果如圖5所示, 圖中可以看出AgileFuzz在相同的時(shí)間內(nèi)發(fā)現(xiàn)了更多的路徑. 我們將對(duì)這一實(shí)驗(yàn)結(jié)果進(jìn)行詳細(xì)的分析,并展示我們的模糊測試工具的優(yōu)勢.
圖5 xmllint程序覆蓋率對(duì)比
為了分析覆蓋率差異, 我們使用afl-cov[19]分析4個(gè)模糊測試工具所發(fā)現(xiàn)的程序覆蓋的差異. 分析結(jié)果顯示, AgileFuzz不僅發(fā)現(xiàn)了EcoFuzz等工具所發(fā)現(xiàn)的全部程序代碼, 還發(fā)現(xiàn)了更多的難以發(fā)現(xiàn)的程序代碼.其中hash.c文件的代碼, AgileFuzz覆蓋率為56.3%,而EcoFuzz等工具為0%, 這是導(dǎo)致程序覆蓋率出現(xiàn)較大差異的主要原因. 我們進(jìn)一步分析產(chǎn)生現(xiàn)象的原因,通過程序分析發(fā)現(xiàn)如圖6所示的調(diào)用序列以及條件判斷. 這里簡單介紹一下CMP9函數(shù), 這是xmllint實(shí)現(xiàn)的定長字符串匹配宏定義, 與C語言自帶的strcmp函數(shù)不同的是, “<”和“
圖6 xmllint程序hash.c調(diào)用依賴
EcoFuzz通過24 h的變異無法產(chǎn)生滿足條件約束的字符串-“
AgileFuzz在通過非確定性變異產(chǎn)生了包含字符串“<**”種子時(shí), 觸發(fā)了cmp9函數(shù)新的覆蓋, 此時(shí)AgileFuzz利用聚類算法確定單一有效變異位置, 確定新覆蓋是由于變異了“<”字符所在的位置. 保存的新種子記錄了關(guān)鍵位置, 能夠?qū)﹃P(guān)鍵位置的后繼位置進(jìn)行持續(xù)性的細(xì)粒度變異, 從而保證了產(chǎn)生“
圖7 種子變異過程
為了驗(yàn)證我們改進(jìn)的模糊測試工具AgileFuzz在通用程序上的測試效果, 我們與近年來效果比較好的Eco-Fuzz、AFLFast以及原始的AFL 2.52b進(jìn)行了實(shí)驗(yàn), 實(shí)驗(yàn)以覆蓋率作為對(duì)比指標(biāo), 選擇了libxml2、binutils等常用的程序作為測試對(duì)象. 在相同的硬件和軟件環(huán)境中進(jìn)行了3次實(shí)驗(yàn), 每次實(shí)驗(yàn)的時(shí)間為72 h, 3次實(shí)驗(yàn)的覆蓋率的平均值作為實(shí)驗(yàn)結(jié)果, 然后計(jì)算覆蓋率對(duì)比圖, 如圖8所示. 通過實(shí)驗(yàn)對(duì)比可以看出, AgileFuzz能夠更快地發(fā)現(xiàn)程序的覆蓋, 并且在不同的程序中效果較為穩(wěn)定.
圖8 多個(gè)程序72 h的覆蓋率比較
如表2所示, 為體現(xiàn)工具的普適性, 我們使用Agile-Fuzz對(duì)字體解析、html解析等多種類型的程序進(jìn)行漏洞挖掘工作, 如: fontforge、harfbuzz、htmlcss、ffjpeg等軟件, 在挖掘工作中發(fā)現(xiàn)了大量的未知漏洞, 經(jīng)過分析確定了漏洞類型, 并將漏洞崩潰樣本以及漏洞分析結(jié)果反饋給作者. 通過在實(shí)際程序中發(fā)現(xiàn)的未知漏洞,證明了AgileFuzz具有發(fā)現(xiàn)實(shí)際程序漏洞的能力.
表2 程序漏洞挖掘結(jié)果統(tǒng)計(jì)
國際很多研究工作都針對(duì)AFL進(jìn)行了改進(jìn). 這些針對(duì)AFL的改進(jìn)主要在種子變異、能量分配方面進(jìn)行了改進(jìn)[20-23], 在確定性變異改進(jìn)方面, FairFuzz[21]根據(jù)是否包括稀有分支跳過部分確定性變異, MOPT[22]詳細(xì)分析了確定性變異效率低對(duì)變異的影響, 并只保留了極少數(shù)的確定性變異, EcoFuzz[19]直接跳過了所有的確定性變異. 在種子評(píng)分改進(jìn)方面, AFLFast[20]使用馬爾科夫鏈對(duì)種子能量分配進(jìn)行建模, 被選次數(shù)更多的和被執(zhí)行次數(shù)較少的種子分配的能量較高. EcoFuzz[19]使用多臂老虎機(jī)對(duì)模糊測試進(jìn)行更準(zhǔn)確的建模以完成能量分配. 但是這些模糊測試改進(jìn)存在以下兩個(gè)問題:
1)變異更加盲目和隨機(jī). 這些模糊測試工具認(rèn)為確定性變異效率較低, 采取的策略是直接跳過全部或大部分確定性變異, 但是只保留非確定性變異的模糊測試在對(duì)種子進(jìn)行變異時(shí)更加盲目和隨機(jī), 無法對(duì)產(chǎn)生新覆蓋的變異位置進(jìn)行持續(xù)的變異.
2)忽視了種子產(chǎn)生的新分支覆蓋數(shù)量對(duì)模糊測試的影響. 種子評(píng)分階段根據(jù)種子大小、種子運(yùn)行速度和種子總分支覆蓋數(shù)量對(duì)種子進(jìn)行評(píng)分, 但是總分支覆蓋數(shù)量越多的種子新發(fā)現(xiàn)的分支覆蓋數(shù)量并不一定越多, 所以新分支數(shù)量多的種子評(píng)分可能很低, 這導(dǎo)致模糊測試將大量的能量消耗在已經(jīng)經(jīng)過多次變異的分支覆蓋, 發(fā)現(xiàn)新覆蓋的能力受到限制, 并且作為影響種子評(píng)分的分支信息缺少程序的靜態(tài)分析.
模糊測試是一種高效的漏洞挖掘工具, 能夠發(fā)現(xiàn)程序真實(shí)的漏洞. 本文設(shè)計(jì)了一種基于聚類算法和新覆蓋的模糊測試改進(jìn)工具, 能夠針對(duì)單一有效位置進(jìn)行持續(xù)性細(xì)粒度變異, 并且利用待測程序的靜態(tài)分析結(jié)果與新覆蓋信息結(jié)合對(duì)種子評(píng)分進(jìn)行調(diào)整, 使得更多的能量分配給新分支, 降低了變異的盲目性. 總體來看, 我們的改進(jìn)取得了較好的效果.模糊測試仍然存在很多的工作需要進(jìn)一步研究, 在將來的工作中, 我們將研究如何針對(duì)程序的長字符串和整數(shù)匹配進(jìn)行拆分,提高針對(duì)關(guān)鍵位置進(jìn)行細(xì)粒度變異的適用性和效率.