蘇文超 費洪曉
(中南大學計算機學院 長沙 410083)
模糊測試是現在流行的漏洞挖掘技術之一.由于其易部署性和在漏洞挖掘方面的高效性,許多軟件公司,如Adobe[1],Cisco[2],Google[3-5],Microsoft[6-7]等,都會在軟件開發生命周期中使用模糊測試來保證產品的安全性.
模糊測試的本質是自動化生成隨機輸入,利用輸入快速執行測試程序,并監控異常執行結果來發現軟件漏洞.這種隨機性可以生成觸發程序異常的非預期輸入,但同時,隨機性也意味著輸入是從輸入空間無方向、無目標地選定.這種盲目性會導致大量冗余、無效的輸入,浪費程序執行時間,而只有少部分輸入能真正完成觸發程序異常的功能.
為了應對隨機性不可避免的性能瓶頸,研究者試圖通過程序的執行反饋信息指導模糊測試,從而幫助提升隨機性種子生成的方向感,但這種智能化的提升也給模糊器帶來一定的性能開銷.
以AFL(American fuzzy lop)[8]為首,覆蓋率引導的灰盒模糊測試(coverage-guided grey-box fuzzing,CGF)較好地平衡了實際應用中反饋指導的性能開銷和漏洞挖掘的效果,成為工業應用最廣泛的模糊測試技術之一,也是目前學術界模糊測試研究的主流內容.國際安全會議上關于CGF的研究內容越來越多,如AFLFast[9],Steelix[10],Vuzzer[11],Angora[12],CollAFL[13],T-Fuzz[14].這些工作對CGF的各運行階段、模糊策略進行了不同程度的改進優化.為了保持CGF的快速發展步伐,有必要對這些改進工作做一個階段性的整合,幫助梳理其碎片化知識,總結其優化方向,從而全面、連貫地認識CGF的最新發展現狀,更明確清晰地進行深入研究.
1.1.1 灰盒模糊測試
模糊測試[15]通過隨機生成輸入來重復運行測試程序,監控程序異常,通過記錄導致異常的輸入定位程序中漏洞的位置.所以模糊測試的核心在于能觸發程序異常的輸入的生成.根據輸入的生成方式分類[16],目前主要分為基于生成的模糊測試(generation-based fuzzing)和基于突變的模糊測試(mutation-based fuzzing).基于生成的模糊測試根據已知的輸入規范建模,然后根據模型生成新的輸入,如Ifuzzer[17],radamsa[18];基于突變的模糊測試先得到應用程序的1組輸入樣本,根據這些輸入樣本通過變異的方法生成新的輸入,如AFL,hongfuzz[19],zzuf[20].
基于突變的模糊測試隨機生成無規則的樣本作為測試程序的輸入,以測試程序的崩潰或停止行為作為輸入是否有效的反饋信息.這種完全脫離程序執行過程的反饋信息指導的模糊測試被定義為黑盒模糊測試.早期的黑盒模糊測試效率低下,大部分輸入無法到達程序的深層分支,只能在邏輯較為簡單的淺層分支發揮有效作用,在代碼復雜度飛躍的現在已經難以發現程序的安全問題[21].
因此,通過程序執行過程的反饋信息指導輸入變異方向的白盒模糊測試開始得到應用.白盒模糊測試可合法訪問測試程序的源代碼,通過重量級的程序分析工具獲取程序執行時的反饋信息.但重量級的程序分析工具往往會大幅增加性能開銷.為了能在可控的性能開銷上提高變異輸入的有效性,人們開始提倡使用灰盒模糊測試.灰盒模糊測試處于白盒和黑盒模糊測試之間,它可以采用輕量級的程序分析工具來獲取粗粒度的程序執行信息.輕量級的程序分析工具使得灰盒模糊測試在同樣時間內較白盒執行更多(百倍甚至千倍)的輸入,因此,灰盒模糊測試的效果甚至能超過白盒[22-23].
1.1.2 覆蓋率引導的模糊測試
模糊測試的目標是覆蓋程序盡可能多的運行狀態,挖掘程序中潛在的漏洞.然而,由于程序行為的不確定性,程序狀態并不能被直觀地測量.研究者因此選擇將代碼覆蓋率作為程序狀態的替代測量指標,即新的代碼覆蓋率的增加近似于新的程序狀態的增加.
覆蓋率引導的模糊測試(coverage-guided fuzzing)率先使用代碼覆蓋率作為程序執行反饋信息指導生成有效的輸入.有效的輸入即能執行程序還未執行過的代碼.基于有效的輸入進行變異,生成的新的輸入更容易遍歷到程序盡可能多的代碼,也更有可能挖掘到這些代碼中的潛在漏洞.AFL在工業上持續的成功經驗證實了這種理念的正確性.利用代碼覆蓋率指導生成覆蓋目標代碼和程序目標路徑的輸入的模糊測試叫作定向模糊測試(directed fuzzing),如AFLGO[24].
1.1.3 覆蓋率引導的灰盒模糊測試
CGF是灰盒模糊測試和覆蓋率引導的模糊測試的組合概念.它通過輕量級的程序分析工具獲取程序執行時的覆蓋信息,并根據覆蓋信息指導輸入生成.
跟蹤輸入在測試程序中的執行路徑可得到準確全面的程序反饋信息,但由于路徑覆蓋會帶來高昂的性能消耗,實際應用中的CGF一般選擇將更粗糙的基本塊作為代碼覆蓋的粒度.自AFL將邊覆蓋引入模糊測試后,研究者發現邊覆蓋可獲得比塊覆蓋更準確的執行信息,邊覆蓋開始成為覆蓋率引導的模糊測試的主流研究方向[13].然而,不管是邊覆蓋還是塊覆蓋,CGF都是通過其覆蓋信息的反饋調整輸入,以期獲得在應用程序上更多的代碼執行,挖掘到潛在的漏洞.
CGF的主流程為模糊迭代過程,主要分為輸入生成和程序測試2個階段.在用戶設置的時間超時之前,CGF不斷重復生成輸入,用輸入執行測試程序,再經由執行的反饋信息指導下一輪輸入生成.圖1展示了典型的CGF流程圖.其中:輸入生成階段包括種子調度和變異操作;程序測試階段包括程序執行和反饋信息收集操作.

圖1 CGF流程圖
模糊迭代以種子s和插樁程序作為輸入.種子s即CGF的初始化種子,其可以由用戶提供也可以由模糊器生成.用戶提供的種子往往比模糊器隨機生成的種子具有更好的輸入格式,更可能通過程序的語法語義檢查而執行到深層代碼.此外,基于高質量的種子進行變異也更容易獲得新的高質量的輸入[25].所以,在實踐中,用戶通常會從網絡或應用程序的測試文檔里提取合法的輸入作為模糊迭代的種子,以提高模糊測試的效果.注意,本文中種子和測試用例皆為插樁程序的輸入.為了區分其在模糊迭代過程中的作用,將保存在全局隊列S中,用于變異的高質量的輸入叫作種子;將種子經過變異操作后,隨機生成的直接用于執行程序的輸入叫作測試用例.
初始化種子作為變異的候選樣本,保存到全局隊列S中(步驟①).然后,種子調度器根據一定的評價標準把種子排好優先級,從隊列S中選擇一個優先級最高,也就是質量最好的種子(步驟②),再根據其質量權重分配該種子相應的能量值(步驟③),此時,下一輪待變異的種子s′已確定.能量是指導變異器生成測試用例數量的指標.能量越高,生成的測試用例數量越多.因此,基于能量值的設置,可以將程序測試的時間資源向高質量的輸入傾斜,從而在有限的時間內找到盡可能多的程序漏洞.此外,各模糊器的種子選擇標準不盡相同,例如,AFL傾向于選擇最小測試用例數量或執行速度最快的種子,AFLFAST傾向于選擇能夠執行到低執行頻率路徑的種子.Shudrak等人[26]基于復雜代碼更容易出錯的猜想,利用軟件復雜度對種子排序.
待變異種子s′傳遞到變異器中(步驟④),同樣地,不同的模糊器可以執行不同的突變策略.AFL采用隨機修改和拼接的突變策略,包括順序翻轉不同長度和步長的位、小整數的順序加減、已知整數(0,1,INT_MAX)的插入等方法[27].變異器根據預設的突變策略,對種子s′進行突變,生成新的1組輸入,即測試用例(步驟⑤).
用生成的測試用例執行插樁程序(步驟⑥和步驟⑦).插樁即在保證程序原有邏輯完整性的基礎上在程序中插入一些探針,從而進行信息采集[28].在CGF中,插樁用于獲取程序執行時的覆蓋信息.AFL根據是否提供源代碼,提供編譯器內插樁和外部插樁2種方式.編譯器內插樁包括gcc模式和llvm模式,在生成二進制代碼時完成代碼段插樁工作;外部插樁即利用qemu[29]在基本塊轉換為TCG塊時完成代碼段插樁工作[30].
程序執行過程中,模糊器持續跟蹤程序狀態,收集程序異常和崩潰信息以及覆蓋率的反饋信息(步驟⑧).如果1個測試用例導致了程序崩潰,或者增加了新的代碼覆蓋,那么該測試用例將保存到隊列S中,等待下一輪的種子調度(步驟⑨).
模糊迭代停止后,將所有測試用例執行到的漏洞信息輸出(步驟⑩).
CGF的偽代碼如算法1所示,遵循與圖1一致的執行邏輯.其中:bitmap為程序的全局覆蓋率位圖,保存整個模糊迭代過程中的代碼覆蓋信息;bitmap′為每輪測試用例t所執行到的代碼覆蓋率位圖.當測試用例t探測到新的覆蓋信息時,該覆蓋信息將被加入bitmap,同時將t作為高質量種子保存到全局隊列S.
算法1.覆蓋率引導的灰盒模糊測試流程.
① 輸入:檢測后的測試程序p、種子s;
② 輸出:缺陷B.
③B=?;
④bitmap=?;
⑤S=s;
⑥ repeat:
⑦s′=Schedule(S);
⑧t=Mutate(s′);
⑨B′,bitmap′=Execute(t);
⑩ ifbitmap′∩bitmap≠? then
S=S∪t;
2.1.1 輸入生成階段的挑戰
1) 種子調度問題.
種子調度策略包括種子選擇策略和能量分配策略2個子部分.目前,在選擇種子時,CGF通常使用單維度評價標準對種子質量進行優先級排序,如文獻[26].這種單一的評價體系簡單、易實現,但容易導致種子偏見和饑餓現象,使得部分高質量的種子無法得到突變的機會去發揮應有的價值.AFL,AFLFAST試圖使用線性權重法[31]計算多維度目標的加權和,并以此作為評價標準.但由于線性權重算法中使用的權重值很大程度依賴于個人經驗,而沒有統計數據支撐,也帶來了經驗主義的問題.
能量分配策略決定了程序測試時對種子的時間資源分配.AFL最初將更多的能量分配給規模較小的執行時間較短的種子.AFLFAST基于梯度下降算法將能量更多地分配給執行低頻路徑的種子.如何合理地評估并量化種子的質量,分配相應的能量,是研究者持續探索的問題.
2) 種子變異問題.
測試用例的質量會直接影響程序測試的效果.因而各模糊器都致力于提高有效的測試用例的生成比例,即盡可能生成既符合程序語法和語義要求,同時能探查到程序漏洞的測試用例.然而,由于突變空間過大,且缺乏有效的突變方向指導,如何對種子進行變異一直都是CGF的難點,也進一步導致當前的CGF方法具有“難以發現特定輸入才能觸發的漏洞”“難以發現多個條件同時滿足才能觸發的漏洞”等問題.
具體來說,突變只有發生在種子的關鍵位置才會影響程序執行的控制流.同時,突變生成的測試用例的選擇也很重要,首選可以增加新的路徑執行測試用例.為了生成更合法有效的測試用例,需要使用程序反饋信息確定種子突變的位置、突變的值,從而確定測試用例突變的方向,縮小突變空間的范圍.但由于CGF只使用輕量級的程序分析工具,因此獲取的覆蓋信息不足以準確定位突變位置和突變值.如何獲取更多的覆蓋反饋信息去指導變異和如何提高現有反饋信息的利用率去縮小突變空間都有待更有效的辦法去解決.
隨著移動互聯網的高速發展,越來越多的應用程序和庫需要處理高度結構化的輸入,如圖像、音頻、視頻、數據庫、文檔或電子表格文件.應用程序在執行之前通常會對輸入進行語法和語義分析.其中:語法分析將原始輸入解析為程序內部數據結構;語義分析對該數據結構進行檢查并執行程序的核心邏輯[32].由于CGF缺乏輸入結構感知,變異操作都是在種子文件的位級上進行的.而位級變異不太可能改變文件結構,使得大多數生成的測試用例在程序執行的早期階段就被語法與語義檢查攔截,無法有效執行到程序的深層次代碼.如何在變異階段對文件結構進行突變,探索到程序的合法輸入格式,從而生成有效的高度結構化輸入,同樣值得思考.
遠程監控系統具體指的所有地方的設備通過一個電腦終端即可進行控制的技術。在電氣工程當中通過此種設計方案不但可以使安裝及材料等成本得到節省,也能夠大大縮減電纜的數量,形成很高的穩定性和組態靈活性,同時達到了生產規模的高效益??墒且驗殡姎夤こ坍斨型ㄓ嵙亢艽?,同時現場總線在通訊速度上還達不到要求,在一些信號較差的區域會造成這種遠程監控方式起不到實際作用,無法開展,因此遠程監控方式的理念只可用到比較小的電氣工程中,不適合整個電氣自動化控制系統。
2.1.2 程序測試階段的挑戰
1) 代碼覆蓋率增長瓶頸問題.
CGF將程序的漏洞挖掘問題轉換為一個優化問題,即如何在有限的時間內,覆蓋盡可能多的程序代碼.利用代碼覆蓋率作為漏洞數量的替代指標[33],程序覆蓋率越高也就意味著發現漏洞的可能性越大.然而,眾多實踐表明大多數測試用例只重復覆蓋相同的部分路徑,而不會發散性地覆蓋更多的路徑[9].如何改變這種情況,提高程序的總體覆蓋率是CGF發展的挑戰與動力[34].
同時,程序校驗也是代碼覆蓋率增長瓶頸的一個原因.魔術數字、魔術字符串、版本號檢查和校驗是程序中常用的校驗方式,而大量的測試用例被這些程序校驗攔截,難以執行到深層代碼.
2) 覆蓋率信息獲取受限問題.
程序分析工具跟蹤測試用例在插樁程序中的執行狀態,基于收集到的程序反饋信息判斷測試用例的質量,決定是否將其加入種子隊列.因此,反饋信息的全面性和準確性對于高質量種子的選擇非常重要.然而,由于只使用輕量級程序分析工具,CGF無法獲取測試用例執行路徑的上下文信息[35].上下文信息對于種子質量判斷非常有效.例如,如果測試用例執行路徑的鄰近代碼都被其他的輸入覆蓋過,那么由該測試用例變異生成的輸入執行到新的路徑的可能性就會很低.那么,該測試用例就不適合作為種子保存.由于種子質量直接關系著程序測試的效果,所以如何獲取更詳細的覆蓋信息,如上下文信息,來正確地選擇高質量的種子成為一個急需解決的問題.
3) 程序分析技術的性能問題.
目前,CGF通常通過高成本的白盒分析技術收集反饋信息,如符號執行技術.由于每個測試用例都能在程序中執行不同的路徑,所以符號執行非常有效.然而,這種有效性是以大量時間開銷和內存開銷為代價的,高開銷使得模糊測試在可擴展性方面受到嚴重限制.
保證CGF的簡單性、高速性、可靠性、可擴展性是程序分析技術集成的前提.重量級分析技術的集成帶來的效果提升不足以抵消性能急劇下降帶來的弊端.例如,檢測工具發現漏洞的可能性提高了10倍,但運行速度卻降低了99%,集成了程序分析技術的智能模式還是不如盲目的隨機模式有效.
隨著應用程序在人們生活中的使用范圍越來越廣泛,其所承受的安全威脅也日趨多元化、復雜化,并因不同的使用場景而呈現不同的威脅特點.例如,高速發展的物聯網設備開始在人們生活中充當重要的角色,按照如今的增長幅度,到2030年,物聯網設備數量將比人類數量還多[36],如此龐大的攻擊范圍使得物聯網對安全漏洞檢測工具有了前所未有的需求.然而,盡管CGF對于通用平臺上的程序漏洞檢測很有效,但由于物聯網設備對實際硬件配置的強依賴性,所以通常不可能直接在物聯網設備上應用模糊測試.為了應對平臺兼容性問題,Zaddach等人[37]試圖使用硬件和軟件仿真相結合的解決方案,Chen等人[38]試圖利用完整的系統仿真技術,但其性能也遠遠不夠理想[23].
將CGF應用到通信協議漏洞檢測上時,也面臨著覆蓋率不高、漏洞挖掘效果差的問題.通信協議通常由服務器/客戶端上的狀態機來實現,狀態轉換由包/消息交換等關鍵協議事件驅動.目前主要使用代理對數據包進行突變和測試[39],但由于缺乏狀態感知,CGF無法引導協議進入感興趣的狀態,并重復使用數據包輸入對其進行測試.此外,在協議中,多端之間的多包通信,既包括非依賴包/字段的消息傳遞,也包括依賴包/字段的消息傳遞.目前CGF使用的單包測試無法有效實現非依賴包之間的代碼覆蓋,而使用多包測試又可能導致不一致的消息傳遞.應用于通信協議的CGF必須面對這些挑戰并提出解決辦法[40].
為了應對CGF面臨的挑戰,研究者試圖通過集成其他技術的長處來彌補CGF的缺陷,從而更精確地收集程序控制流和數據流信息,利用收集到的信息生成更具針對性的輸入,以更好地指導程序執行階段的路徑探索.目前,符號執行和污點分析是使用較廣泛的技術,隨著機器學習技術的成熟,機器學習在CGF中的應用也越來越多.
3.1.1 符號執行
靜態分析是指不執行程序的狀態下,利用詞法分析、語法分析、控制流等技術對代碼進行掃描,并對其程序行為進行分析的技術.根據分析目標可分為源代碼分析和二進制分析.近年來靜態分析向模擬執行技術發展,通過符號執行、抽象解釋等技術可以發現很多傳統意義上動態測試才能發現的缺陷,如未對參數進行邊界檢查而造成的緩沖區溢出、堆溢出等漏洞[41].
靜態分析容易集成到開發環境中,自動化程度較高.早期靜態分析中的符號執行技術被廣泛應用于模糊測試中,一些灰盒或白盒模糊器利用符號執行提高測試覆蓋率,如EFFIGY[42],Prefix[43],Prefast,ARCHER[44]等.
符號執行的概念由Boyer等人[45]提出,其主要思想是使用符號變量代替具體數值作為程序輸入,在模擬程序執行過程中收集與輸入符號變量相關的路徑約束條件,計算符號變量的具體值,生成能夠引導程序執行該路徑的測試數據.
但由于缺乏程序運行時信息,符號執行難以完全模擬程序執行,使得分析不夠精確.為解決該問題,研究人員提出了混合符號執行的概念,將符號執行從靜態分析技術轉變為動態分析技術.其核心思想是在程序真實運行過程中,判斷哪些代碼需要符號化執行,哪些代碼可直接執行,代表性的工具有EXE[46],CUTE[47],DART[48],SymFuzz[49]等.符號執行可能帶來狀態爆炸的問題,由此也發展出了動態符號執行的概念.動態符號執行是將路徑限制在一個具體的路徑上,程序只能觸發該路徑下的bug或者發現一個新的路徑,以減少正在研究的狀態數量,并用具體數值替換復雜表達式,降低程序復雜度[50].
3.1.2 污點分析
污點分析技術是信息流分析技術的一種,它將系統或應用程序中的數據標記為污點或非污點,如果污點數據在傳播時影響到非污點數據,則該非污點數據被標記修改為污點.若污點標簽隨數據傳播到指定存儲區域或信息泄露點,則認為該系統違反了信息流策略.污點分析也可以分為靜態污點分析和動態污點分析[51].
靜態污點分析是指在不運行程序的情況下,通過詞法、語法分析等方法分析變量間數據和控制依賴關系,如賦值、函數調用、別名等;動態污點分析旨在程序運行過程中,跟蹤并記錄變量、寄存器等值,通常采用插樁的方法,在不破壞原有程序邏輯的基礎上插入采集信息的代碼,從而獲得程序運行的相關信息.污點分析技術首先對污染源進行定位,然后監測污染數據在軟件中的傳播,最后根據污點匯聚點獲取關鍵信息[52].靜態分析考慮了程序所有可能的執行路徑,但不運行無法分析準確的漏洞點;動態分析則可以獲得程序運行中的具體信息,分析精度較高,但頻繁的插樁和影子內存會占用大量系統資源[53],并且只能分析執行到的路徑,存在一定的誤報.所以有研究者將二者進行了結合,先執行靜態污點分析獲得初步信息,提高路徑覆蓋率,然后執行動態污點分析獲得漏洞的具體信息,提高精度[54].
由于很多軟件的源代碼無法獲取,所以動態污點分析經常被運用.模糊測試的核心思想是生成大量測試用例保證較高的代碼覆蓋率從而對程序進行檢測,污點分析的引入使模糊測試可以更好地理解漏洞點.此外,動態污點分析與符號執行相結合,更好地提升了具有校驗機制的程序進行模糊測試的效率.
3.1.3 機器學習
機器學習旨在模擬人類的學習活動,從對數據的自動分析中獲得規律,并利用規律對未知數據進行預測.因為機器學習算法中涉及了大量的統計學理論,機器學習與推斷統計學聯系尤為密切,也被稱為統計學習理論.機器學習算法包括分類算法、聚類算法、回歸算法等.
模糊測試隨機初始種子集通常很難達到很好的效果,這是由于:種子生成是隨機的,沒有較好的指向性;測試失敗時不能總結規律,從而導致大量重復;種子文件較高的代碼重復率使得無法測試深度漏洞.引進機器學習可以很好地解決這類問題.例如,Wang等人[55]利用深度學習網絡,將惡意html樣本的文件結構作為訓練集,訓練深度學習模型,生成帶有部分針對瀏覽器漏洞的惡意代碼,產生更有針對性的種子文件.
3.2.1 輸入生成階段改進
輸入生成階段又可分為種子調度階段和突變階段.
在種子調度階段:Vuzzer[11]利用程序感知的模糊策略,通過在程序測試期間對程序進行輕量級靜態和動態分析推斷控制流特性,使得Vuzzer[11]可優先選擇執行深度路徑的種子進行突變.CollAFL應用3種不同的策略優先選擇具有更多未覆蓋的相鄰分支或后代的種子.Cerebro[35]使用了一個在線多目標算法,通過平衡代碼復雜度、代碼覆蓋率、執行時間等指標選擇種子.同時引入輸入潛力概念分配種子能量,即通過預測種子對未覆蓋代碼的覆蓋潛力而不是對已覆蓋的執行跟蹤來評估輸入.FuzzFactory[56]將提高代碼覆蓋率的輸入放入種子隊列,同時將特定域相關的中間輸入放入種子隊列,從而提高特定域的模糊測試覆蓋率.
在突變階段:Hybrid-Fuzz[56]利用符號執行收集關注的程序路徑上的約束條件,使用約束求解生成能實際覆蓋該路徑的測試輸入,以達到檢測測試程序特定代碼點的功能;Skyfire[55]應用數據驅動種子生成策略,以語料庫和語法作為輸入,學習概率上下文敏感語法(PCSG),以指定語法特征和語義規則,然后利用學習過的PCSG生成種子輸入;AFLFast將CGF建模為馬爾可夫鏈,指定從執行路徑i的種子突變生成能探索到路徑j的測試用例的概率pij,并根據概率指定分配相應的程序執行時間;AFLsmart[32]針對需要處理復雜文件格式的應用程序,利用種子文件的高級結構來生成新文件.將變異的粒度由位級變更到文件級,從而在保持文件有效性的同時探索全新的輸入域;Neuzz[33]應用了一種新的程序平滑技術,該技術使用代理神經網絡模型,可以增量地學習一個復雜的、真實世界的程序的分支行為的平滑近似,這種神經網絡模型可以與梯度導向的輸入生成方案一起使用,生成能探索到新路徑的輸入;Zest[57]通過參數生成器將輸入從簡單的參數域轉換為更結構化的域,如語法有效的XML,從而使參數級突變能夠映射到測試輸入中的結構突變,生成語義有效的輸入;Superion[58]基于語法感知覆蓋的灰盒模糊方法處理結構化輸入.將每個測試輸入解析為一個抽象的語法樹,進而引入一種語法感知的調整策略,在保持輸入結構有效性的同時調整測試輸入;Choi等人[59]利用動態符號執行最大限制地將灰盒變白,生成能滿足分支條件的測試用例;SLF[60]利用AFL來識別輸入有效性校驗以及對此類檢查有影響的輸入字段,然后根據這些校驗與輸入的關系對輸入進行分類,包括算術關系、對象偏移量、數據結構長度等,提出多目標搜索算法以應用特定類別的變異.
3.2.2 程序測試階段改進
在程序測試階段,CGF會持續跟蹤輸入在測試程序中的執行狀態,提取相關的反饋信息,指導如何探索新的路徑,并挑選出有價值的高質量種子放入種子隊列.研究者們針對該階段覆蓋率信息獲取的準確性、全面性挑戰和覆蓋率增加的挑戰做了大量工作,其中,性能開銷的降低是伴隨著覆蓋率信息獲取或覆蓋率增加的過程而實現的.
在覆蓋率信息獲取問題上,CollAFL[13]分析了AFL代碼覆蓋率計算存在的哈希碰撞問題,并提出了新的哈希算法以提高覆蓋率信息的準確度.Intel處理器提供Intel PT(Intel processor trace)完成觸發和過濾功能,實時地跟蹤執行過程,獲取更準確的覆蓋信息[61].Intel PT具有執行速度快、無源依賴等優點[30].Nagy等人[62]基于大多數測試用例都是無效輸入的觀點,提出將覆蓋率信息用于指導跟蹤的方法,只跟蹤增加代碼覆蓋率的測試用例,從而獲得更快的速度.
為了突破覆蓋率增長瓶頸,很多研究者都試圖在突破程序約束及路徑檢查工作上作改進.符號執行具有天然的優勢,可識別執行過程中的阻塞點,幫助模糊器通過程序控制流程中復雜的條件判斷.例如:Driller[63]利用動態符號執行生成滿足特定條件要求的值,繞過條件判斷,從而找到更深層次的漏洞,且為了降低性能開銷,只有CGF在一定時間內無法取得任何進展時,才會啟動動態符號執行;Wang等人[64]提出了一種“最佳轉換”策略,分別通過模糊測試和約束執行來量化探索每條路徑的成本,并選擇更經濟的方法探索該路徑;Zhao等人[65]提出“區分派遣”策略,基于蒙特卡洛的概率路徑優先級模型量化每條路徑的難度并排列優先級,將動態符號執行傾斜于最困難的路徑計算,從而緩解路徑爆炸問題,增加模糊測試效果.
T-Fuzz[14]刪除了代碼探測路徑上的完整性檢查,使用符號執行檢測刪除操作所導致的誤報問題;Pak[66]提出“區別調度”策略,通過量化探索每條路徑的成本,對路徑進行優先級排序,使用協同執行計算優先級最高的路徑,從而避免了路徑爆炸問題,更經濟有效地完成對路徑的探索.REDQUEEN[50]基于部分輸入直接對應于運行時的內存和寄存器這一觀察,通過跟蹤程序比較指令中的使用值,創建輕量級的近似污染跟蹤,使用快速模糊過程驗證是否觸發了新的和潛在的行為.
為了應對物聯網設備的兼容性及性能問題,FIRM-AFL[67]在系統模擬器中模擬的posix兼容固件上應用CGF來解決兼容性問題,并使用一種稱為增強流程仿真(augmented process emulation)的新技術將系統模式仿真和用戶模式仿真結合起來,兼具了系統模式仿真的高兼容性和用戶模式仿真的高吞吐量,從而突破系統模式仿真所導致的性能瓶頸.
Chen等人[68]提出了針對通信協議的有狀態協議模糊策略,探索與不同協議狀態相關的代碼,從而實現更高的代碼覆蓋率.具體來說,該狀態模糊器在測試程序執行時創建多個狀態,并識別用于不同狀態的包和字段,根據動態執行的模糊效果,選擇合適的時間復制協議狀態、前進到下一個協議狀態或回滾到前一個協議狀態,多次重復從而確定最高代碼覆蓋率的最佳點,實現最大的代碼覆蓋率和代碼執行深度.
模糊測試在挖掘真實軟件中的安全漏洞方面取得的巨大成功極大促進了研究者的研究熱情.近年來,越來越多的模糊測試策略和算法相繼被提出.每當一種新的模糊算法被提出時,必須在實驗上證明它優于現階段的模糊算法.
目前,對于模糊器的實驗評估,主流方法是:首先,選擇一個現階段先進且性能令人信服的模糊器作為比較對象,近年來,將AFL作為比較對象是眾多研究的選擇.其次,選擇1組用于測試模糊器效果的測試程序.測試程序主要分為實際可用的程序,如:谷歌模糊測試組件、readelf、nm、objdump等開源程序;人工構造的程序,如CGC,LAVA-M數據集,這些數據集都被人工注入了漏洞,以測試模糊器挖掘漏洞的能力.在相同的運行環境下比較需要評估的模糊器和作為比較對象的模糊器在尋找漏洞方面的效率和效果.通常情況下,將找到漏洞的速度、找到新的CVE漏洞數量、程序代碼的覆蓋率作為評估標準,以證明模糊器的真實有效性.
Klees等人[69]對2012—2018年發表的32篇模糊測試論文的實驗評估部分進行了重新評估,其結果表明,沒有一個模糊測試的評估實驗能正確執行所有符合規范的評估流程和評估標準.而評估流程和評估標準的差異性確實可以轉化為有誤導性或不正確的評估結果.根據Klees等人[69]的工作結果,繼續對2018—2019年所發表的模糊器論文的實驗評估作統計調查,結果如表1所示:

表1 模糊器實驗評估數據總結
測試對象:R表示實際程序,C表示CGC數據集,L表示LAVA-M基準,G表示谷歌fuzzer測試套件.
性能方差:不同輪數的模糊測試的性能差異方差.A表示置信區間.
崩潰分類:S表示用堆棧哈希對相關崩潰進行分組,O表示用其他工具/方法分類,B表示用覆蓋率信息對崩潰分類,F表示用現實依據進行崩潰分類.
覆蓋率指標:L表示行/指令/基本塊覆蓋,M表示方法覆蓋,E表示控制流邊或分支覆蓋,Z表示其他覆蓋信息.
種子:H表示隨機取樣種子,M表示手工構建種子,T表示自動生成種子,N表示未預設有效性的非空種子,V表示預設有效的種子,但不清楚該種子的獲取途徑,Y表示空種子,/表示在不同的程序用了不同的種子.
盡管研究者都盡量設置了客觀有效的實驗以增加結果的可信度,但由于缺乏統一的評估流程、評估指標,還是難以在現實中用統一維度證明這些模糊器的進步性.主要問題分析如下:
1) 參考對象選擇不統一.盡管大部分研究都選擇將AFL作為比較對象,但仍有一些選擇了其他參考對象,如REDQUEEN[50].且近年來眾多模糊器都是在AFL的基礎上進行改進,一些研究會傾向于選擇與更先進的模糊器進行比較,以證明取得的進步.由于參考對象選擇范圍的廣闊性,充當參考對象的模糊器在各評估指標上表現的差異性,客觀的參考標準難以確定.
2) 測試程序選擇不統一.通常情況下,模糊算法的進步性在測試程序上得到驗證后,希望其性能優越性能在現實生活中的大部分程序中體現出來.即模糊器在測試程序上的良好性能能轉化為總體上的良好性能,這就要求測試程序具有一定的代表性.目前沒有代表性的測試基準能滿足這些要求,因此不同的模糊器往往會自主選擇測試程序.部分研究會傾向于選擇模糊器表現優異的程序進行測試,這使得客觀評判模糊器在現實運用中的真實性能更加困難.
3) 測試時間設置不統一.目前模糊器的超時時間設置通常從1 h到幾天或幾周不等,常見的選擇是24 h,5 h,6 h.大多數研究都沒有給出合理的超時報告.然而,算法之間的相對性能會隨著時間的變化而變化,較短的運行時間可能會造成誤導,產生不完整的結果.
4) 測試輪數選擇不統一.由于模糊測試本身的隨機性,對測試程序的每次模糊測試都可能產生不同的結果.所以,僅僅進行1輪測試就比較它們的性能是不夠的.
5) 初始種子的選擇不統一.不同的初始種子會造成差異化的測試結果.然而,大多數研究對種子的選擇很隨意,顯然認為任何種子都同樣有效,且沒有提供細節.
6) 評估標準不統一.目前,直接評估模糊器所挖掘的漏洞數量是主流方法.然而,也有部分研究使用代碼覆蓋率或程序崩潰的去重輸入數量評估模糊器的性能改進.
如表1所示,沒有研究完全遵循評估準則,因此對CGF的評估流程提出了如下建議:
1) 所有測試應該持續至少10輪,且統計其總體方差,用統計學相關知識正確評估模糊測試算法性能,防止隨機性.
2) 每輪測試應該維持足夠長的時間,并繪制發現bug數量隨時間變化曲線,對比不同模糊測試算法性能.
CGF作為目前流行且發展潛力巨大的漏洞挖掘工具之一,其未來的發展前景是值得期待的.本節大膽猜想了未來可能的發展方向,以供參考.
通用的CGF技術已經成熟,并且在程序的初期漏洞檢測中取得了較大的成功.然而,隨著CGF所應用的領域越來越廣,測試程序的輸入格式越來越復雜和多樣化,針對具體應用場景實行專業化的智能指導型CGF有待進一步發展.結合相關應用場景的理解和特征分析,CGF能對模糊過程實現更精確的控制,更快更準確地挖掘程序中的深度漏洞.目前,傳統的靜態和動態分析對CGF的性能提升已經發展到了瓶頸期,更輕量級的替代技術或模糊策略還在持續提出.同時,隨著機器學習的發展,機器學習技術也將在與CGF的結合中發揮更重要的作用.
如第4節所述,不統一的評估流程、不同的測試程序和評估指標都會給評估結果帶來誤差或錯誤.這些誤差或錯誤不僅給模糊器間的性能比較帶來困難,同時也可能誤導相關研究者相信誤差后的性能效果,從而投入更深的研究中,造成研究人力的浪費.因此,建立一套統一的、可靠的模糊測試評估系統是有強烈現實需求的.評估系統可通過包含足夠數量、各種大小的程序來體現現實程序的多樣性,同時設置統一的評估指標對不同的模糊器進行同維度的比較.
目前,模糊測試技術的主要創新研究集中在如何更有效地挖掘漏洞上,對于模糊測試實際應用中的可解釋性和量化性的研究還遠遠不夠.例如:經過模糊測試后,程序的安全性究竟能得到多大程度的保證;如何有效地評估停止模糊測試后的剩余風險,即攻擊者找到模糊測試沒有找到的漏洞的風險;如何判斷停止模糊測試的合理時間.目前,上述判斷都依賴于研究者的個人經驗,而不能根據測試過程中觀察到的程序行為進行統計上有根據的推斷.因此為未發現的漏洞設置合理的剩余風險閾值,并用可行的統計框架對剩余風險進行量化是解釋和量化模糊測試的必要工作.B?hme[78]提出了一個總體框架,可作為解決這一挑戰的一個起點,并討論了未來研究的具體機遇.
隨著分布式技術的不斷發展,當前分布式技術已經能夠對大量計算單元進行整合,完成大規模的問題求解任務.如何變異出更多有效的測試用例,以及CGF在種子變異過程中產生的海量測試用例,一直都是制約CGF性能的關鍵因素.將分布式技術與CGF相結合,通過大量分布式計算機并行執行模糊測試任務,可以有效提高CGF在輸入生成階段和程序執行階段的性能.