金童
(北方工業大學,北京 100144)
模糊測試是一種基于缺陷注入的自動化軟件漏洞挖掘技術通過向待測試的目標軟件輸入測試用例并執行程序,監控程序的運行狀況,同時記錄并進一步分析目標程序發生的異常,進而通過分析造成目標程序崩潰的測試用例來發現目標程序潛在的漏洞。
在模糊測試的過程中,測試用例執行、異常監視這兩個重要的過程完全可以自動化實現。
模糊測試在挖掘的漏洞數量方面具有很大優勢,與此同時,其不足也十分明顯。比如:對訪問控制漏洞無能為力、無法發現糟糕的設計邏輯、無法識別多階段安全漏洞和無法識別多點觸發漏洞。
模糊測試的高效性嚴格依賴輸入測試樣本的質量,因此模糊測試的核心就是核心測試樣本的生成,其有兩個關鍵點:(1)優質的測試樣本種子;(2)合理的畸變策略。針對第(1)個關鍵點,以目標為導向選擇確定優質測試樣本種子,比如:能夠發現未執行過的路徑或者執行率較低的路徑;向某個特定待測試區域不斷逼近等。
目前常用的漏洞挖掘技術分為靜態分析、動態分析、二進制比對、模糊測試等。靜態分析是指在不運行軟件的前提下進行的一種分析技術。其主要通過對目標程序的詞法、語法、語義分析來發現軟件中潛在的安全漏洞,特別是函數調用中參數的來源以及函數返回值,通過對參數進行來源分析與跟蹤,很容易發現其中未對參數進行邊界檢查而造成的緩沖區溢出、堆溢出等類型的安全漏洞。動態分析是一種通過動態加載并運行的目標軟件,監測程序運行時的堆棧信息、內存使用情況、變量的值等狀態信息以及程序的輸出來驗證或發現軟件漏洞的技術。二進制比對也稱為補丁比對。作為軟件安全漏洞的補救措施,軟件開發商會定期或不定期地提供相應的修補程序即補丁。模糊測試是一種基于缺陷注入的自動化軟件漏洞挖掘技術,其基本思想與黑盒測試類似。模糊測試通過向待測試的目標軟件輸入一些半隨機的數據并執行程序,監控程序的運行狀況,同時記錄并進一步分析目標程序發生的異常來發現潛在的漏洞。
在模糊測試的過程中,測試用例執行、異常監視這兩個重要的過程完全可以自動化實現。而且,通過模糊測試技術發現的漏洞一般是真正存在的(原因是對半有效數據的處理不當),即模糊測試技術存在誤報率低的優點。其他的漏洞挖掘方法往往需要對目標程序的源代碼或二進制代碼進行深入的分析,這是過程的開銷巨大,而模糊測試并不需要對目標程序的源代碼或二進制程序進行分析即可進行。
我們這次使用的就是模糊測試中的灰盒測試。灰盒測試使用輕量級工具來以可忽略的性能開銷確定輸入所執行的路徑的唯一標識符。通過改變提供的種子輸入來生成新輸入,如果新輸入使用了有趣的新路徑,則會添加到模糊器的隊列中。AFL負責發現數百個高影響力漏洞,已被證明可以“憑空”生成有效的測試文件,并且擁有大量的安全研究人員致力于擴展它。
AFLGO作為定向灰箱模糊器,重點關注用戶定義的目標位置并進行優化,根據自定義的功率計算方法來生成更短距離的測試種子。此處,距離是根據輸入種子執行軌跡上的基本塊到目標基本塊的平均權重計算的,其中權重由程序的調用圖和過程內的控制流圖進行的過程內分析得到,并且自定義的功率計算方法是基于模擬退火的。
在實際情況下,生成的大量輸入無法讓程序執行到目標,這極大地影響了模糊測試的效率。為了使模糊的效率更高,我們在AFLGO的基礎上對種子篩選部分進行了優化,它可以更高效地找到導致程序崩潰的種子。我們使用一種前饋神經網絡,這是一種高效且可擴展的程序平滑技術,該技術可以模擬程序的分支行為。并且可以使種子進行更為高效的突變,最終可以使模糊測試的效率進一步提升。
按測試輸入的不同種類進行劃分,模糊測試的測試輸入可分為基于變異和基于生成兩種方式。其中,基于變異的模糊測試在修改已知測試輸入的基礎上生成新的測試用例,而基于生成的模糊測試則是直接在已知輸入樣本格式的基礎上生成新的測試輸入。
根據不同的研究側重點,本章分別介紹基于變異的模糊測試、基于生成的模糊測試。
AFLFast[1]采用特定的策略引導AFL優先選擇低頻路徑的文件作為種子文件進行變異,以此在相同的測試時間內探索更多的路徑。AFLGo[2]采用了模擬退火算法對種子進行賦能操作,為更接近目標點的種子給予更多的能量,從而可以篩選出更為優質的種子,使得模糊測試的效率進一步提高。
基于生成的模糊測試主要基于模型或者語法生成能滿足程序語法和語義檢查的測試輸入,常用于高度結構化的測試輸入生成。

圖1 AFLGo模型圖Fig.1 AFLGo model diagram
SeededFuzz[3]使用各種程序分析技術來促進初始種子的生成和選擇,這有助于實現定向模糊的目標。配備改進的種子選擇和生成技術,SeededFuzz可以到達更多關鍵站點并發現更多漏洞。
當前的導向性模糊測試旨在生成可能到達特定錯誤代碼的輸入,進一步期望觸發該錯誤。但是在模糊測試過程中,生成導致程序錯誤輸入的效率卻并不高。在有限的時間內生成盡可能多的可以導致程序崩潰的輸入就作為下一步的研究目標。而且在模糊測試過程中目標程序的執行時間占最大比例,只有增加優質輸入(可以導致程序崩潰的輸入)的生成才能大大提高模糊測試的效率。如果存在一種足夠快的方法來生成更多優質輸入的方法,則在有限的時間就能找到更多有效的引起程序崩潰的種子。這樣,可以提高模糊測試的整體性能。
AFLGo的模型如圖1所示,主要由四個部分組成:圖形提取器、距離計算器、運行器和模糊器。
(1)圖提取器生成調用圖和相關的控制流圖。是作為AFL LLVM pass的擴展而實現的,它由編譯器AFL clang fast激活。
(2)距離計算器利用調用圖和每個過程內控制流計算每個基本塊的進程間距離。DC被封裝為一個Python腳本,它使用networkx包來解析圖,并根據Djikstra的算法進行最短距離計算。DC生成BB距離文件,該文件包含每個基本塊級目標距離。
(3)儀器獲取BB距離文件,并在目標二進制文件中指示每個BB。對于每個BB,它確定各自的BB級目標距離并注入擴展的蹦匯編代碼,在每個跳轉指令之后執行,以跟蹤覆蓋的控制流邊緣。對于每個基本塊,AFLGo儀器添加匯編代碼:1)加載當前累積距離并添加當前BB的目標距離,2)加載并增加已運行BB的數量,3)將兩個值存儲到共享內存中。
(4)Fuzzer根據我們加入樣本種子快速收斂篩選算法的退火功率計劃,并模糊化插入二進制文件。當前種子距離的計算方法是將累積的基本塊距離除以訓練基本塊的數量。
我們基于退火的功率計劃為“更接近”目標的種子分配了比“更遠”的種子更多的能量,并且這種能量差隨溫度降低而增加。
在模糊測試的起始階段,首先對種子進行距離測量,及種子到目標點的距離。該測量結果在進行檢測時已經完全確定,并且在運行時可以有效地計算出來。我們的程序分析是基于調用圖和程序內控制流圖進行的過程內分析,這與過程間分析相比可以節省很多時間。
首先我們使用前饋神經網絡來模擬復雜的程序分支行為,進行有效的梯度計算。我們通過使用經過AFLGo測試過一定時間后的測試輸入語料庫來訓練神經網絡。
隨后我們使用梯度或高階導數來實現更快的收斂性,平滑的神經網絡模型一旦經過訓練,便可以用于有效地計算梯度和高階導數,然后可以利用它們來更快地收斂到最優解,也就是得到更為高效的種子。
和AFLGo類似,我們定義了一種距離度量(即種子到目標位置),該度量在進行模糊時已完全確定,并且可以在運行時有效地計算出來。盡管我們的度量是過程間的,但我們的程序分析實際上是基于調用圖和控制流圖進行的過程內分析。與過程間分析相比,我們展示了如何產生二次儲蓄。而且調用圖和控制流圖在LLVM編譯器的基礎結構中很容易得到。
使用這種新穎的距離度量,我們定義了一種新穎的功率方法,該方法集成了最流行的退火功能,即指數冷卻計劃。根據我們的距離測度,基于退火的功率計劃逐漸將更多的能量分配給更接近目標位置的種子,同時減少更遠的種子的能量。
最后,我們結合了一種新的方案平滑方法,它使用代理潛虧神經網絡模型來學習和迭代地平滑逼近目標程序,目的就是通過觀察到的程序行為來精煉目標程序。這樣就可以替代神經網絡可以平滑地延展到觀察到的程序行為,同時還可以對潛在的非線性和非凸行為進行準確建模。
同時我們通過梯度計算方法實現了新的邊緣覆蓋,這樣我們就可以在保留就數據的同時還可以觸發新的分支,從而生成新的訓練數據。再將新的數據和過濾掉的舊數據重新訓練神經網絡,這樣就能有效的防止訓練數據樣本數量無休止的增加,大大增加了重新訓練的次數。
為了顯示我們工具的有效性,我們評估了配備工具后的AFLGo和原始的AFLGo,使用LAVA-M中的4個程序uniq、md5sum、who、base64,對比其他工具的測試方法,大部分都是把測試時間都控制在了7天左右,所以我們也將用同樣的時間測試數據,這樣對比結果就具有很高的有效性。
所有實驗和測量均在運行Ubuntu 16.04,具有8核CPU,16GB內存和2TB硬盤的64位服務器上進行的。根據實驗結果,我們的工具可以將模糊測試的性能提高到AFLGo的1.5倍多。對比AFLGo本身,改進后模型的測試結果都要明顯好于AFLGo,總漏洞數以及去重后的漏洞數量都比之前的數量要多得多。
最近,導向型模糊測試可以有效地發現具有潛在已知位置的錯誤。為了提高模糊測試的效率,本文提出高效的樣本種子快速收斂篩選算法以使模糊測試在更短的時間內可以找到更多的漏洞。并且我們是在AFLGo框架的基礎上進行實現的,這樣利于對比實驗的進行,使結果更有說服力。對LAVA-M中4個程序測試的結果表明,我們的工具可以使速度提高多達1.5倍以上。