【摘 要】 為有效提高嵌入式軟件在投入生產環境前發現潛在安全問題的效率,本文對嵌入式環境下軟件開發中的代碼安全控制進行了深入分析與研究,闡述了在資源受限環境下軟件安全測試的方法和技術,并重點介紹了在軟件編譯鏈接之后,通過對二進制文件進行測試進一步發現嵌入式軟件安全問題的方法。
【關鍵詞】 嵌入式 代碼安全 模糊測試
1 引言
據調查顯示,全球嵌入式系統市場收入在6年內增長達40%,從2015年的1590億美元增長到2021年的22534億美元。這一增長的主要驅動力是市場對節能、智能的電子設備日益增長的需求。此外,行業提供的新可能性及在嵌入式系統中使用多核架構提供的新應用也加速了這種增長。嵌入式系統是一種包含微處理器和軟件的電子產品,廣泛應用于工業生產、醫療電子、汽車電子、網絡通信、軍事航天等領域。嵌入式系統一般都包含相對固定的組件,如芯片、閃存、固件等。組件組成主要包括硬件和軟件部分,其中軟件部分直接與硬件交互,因此對于其安全性和可靠性有著更高的要求。
近20年來,有關嵌入式軟件的零日(0Day)漏洞層出不窮,而分析其中大多數漏洞成因往往是較為低級的錯誤導致的。如果能在軟件的開發階段或應用驗證階段通過一系列測試方法及流程,將可能引發的安全問題盡可能規避掉,將大大提高軟件的安全性。這一需求在無法經常更新迭代的嵌入式環境下顯得尤為重要。本文將針對C/C++環境的嵌入式系統中常見的軟件安全問題進行討論,并介紹幾種常見的測試方法,以提高嵌入式軟件的安全性、健壯性。
2 嵌入式系統常見的安全問題
在安全方面,針對嵌入式系統的攻擊可大體分為3類,分別是針對嵌入式軟件的攻擊、針對網絡的攻擊和側信道攻擊。本文將針對嵌入式軟件的安全問題和幾種常見的影響系統穩定性的編碼問題進行討論。
2.1 緩沖區溢出漏洞
緩沖區溢出是各類軟件中十分普遍的安全問題,不僅在嵌入式軟件中存在,在其他應用軟件和操作系統中也十分常見。表1為國家信息安全漏洞庫(CNNVD)收錄的2022年6月漏洞類型統計表,從表中可以看出緩沖區錯誤類型漏洞占比高達8.4%。緩沖區溢出問題的根本原因在于過于信任輸入,而沒有正確檢查動態空間的邊界,開發者將長于目標的數據進行拷貝,因此覆蓋了與目標相鄰的區域。緩沖區溢出的問題十分嚴重,可能導致目標系統宕機、命令執行等后果。實踐得出,緩沖區溢出可以發生在堆、棧、bss等存放變量的任何區域,攻擊者可以通過事先計算好的長度構造payload來修改函數的返回地址,或替換成惡意代碼的起始地址,以完成攻擊。
表1 2022年6月漏洞類型統計表(只截取前10種)
2.2 內存泄漏
內存泄漏是指程序中已被動態分配的堆區內存由于編程人員或者其他原因而未進行釋放,造成的系統內存浪費,內存泄漏問題并沒有泄漏大小之分,無論內存泄漏多么輕微,都會導致程序運行性能降低,最終將會在有限的時間內消耗掉全部內存,導致系統的崩潰。內存泄漏問題在嵌入式系統下顯得格外重要,嵌入式系統的內存資源通常比其他平臺要小得多,如果存在內存泄漏問題,將在更短的時間內造成嚴重后果。
2.3 空指針引用
空指針引用顧名思義就是使用了一個沒有指向合法地址空間的指針,通常是由這個指針沒有被初始化、正確賦值或原本指針指向的內存空間已經被釋放等原因導致的。如果編程人員在使用一個指針之前沒有對其進行非空判斷,都有可能造成空指針引用,原因是在C/C++環境中即使使用了malloc/new內存分配函數對其賦值,如果不對返回結果進行檢查,也無法確保此時的內存分配是成功的。空指針引用問題比內存泄漏問題更為嚴重,因為前者可能導致系統直接崩潰。
2.4 格式化字符串漏洞
格式化字符串漏洞主要利用C語言中print系列的函數,如printf、sprintf、fprinf等C庫函數。格式化是為了控制顯示文本的樣式,如%d是以整數的形式輸出,%p打印指針地址等,在使用此類函數前,如果能給定預料之內的參數,并不會有任何安全問題。但是若對輸入格式不進行控制,支持用戶任意輸入,將會造成嚴重的安全問題。其攻擊原理可以泄露特定寄存器和棧上的值,從而給攻擊者創造了發揮的空間,造成系統內存信息泄露、控制代碼執行邏輯、遠程命令執行(RCE)等嚴重后果。
3 嵌入式軟件安全測試的方法和技術
3.1 靜態測試
靜態測試主要通過靜態測試工具對軟件的源代碼進行安全掃描,一般靜態測試常用的工具有Fortify SCA(Static Code Analyzer)、VCG(Visual Code Grepper)等。此類工具的基本思想都是從源代碼中提取原始特征,如字符串、基本塊、指令序列、語法樹、函數調用圖等,之后再對這些特征與先準備的軟件安全規則庫進行匹配來確定源代碼中是否存在相應的漏洞。靜態分析是在不執行源程序的情況下對代碼進行安全檢測的方式,它包含很多方面的技術,如控制流分析、數據流分析、常量傳播和指針分析等。靜態測試作為一種保證源代碼安全的測試方法,可以較為有效地檢測出空指針引用、格式化字符串等問題,將軟件的安全問題控制在編碼階段。靜態測試的流程如圖1所示。
圖1 靜態安全測試流程
3.2 動態測試
動態測試是針對軟件或系統非常有效的測試方法,同時也是使用最多的針對嵌入式設備的動態漏洞分析技術。動態測試是在真實環境或者模擬環境中對運行中的程序通過對輸入進行隨機變換,觀察在不同的輸入下程序的運行結果,分析和判斷其結果是否滿足預期。例如,對于內存泄漏問題,通常可以使用一些開源的內存泄漏掃描工具,在被測程序源碼中進行插樁,檢查程序從開始到運行結束的內存釋放情況。當然,無論何種工具,都存在誤報的情況,但使用工具的好處是可以盡量縮小范圍,再由研究人員分析當前結果是否為安全問題。
動態測試在理論上幾乎可以驗證所有存在的安全問題,其誤報率也比靜態測試少。但是,動態測試也存在著過于依賴程序運行、程序分支路徑覆蓋不全、漏報等缺點。動態測試還與測試人員的能力及測試用例的準備密切相關,如果被測系統規模過大,測試用例集合也隨之增大,則會導致漏報率提高。
3.3 嵌入式軟件二進制模糊測試
靜態和動態測試方法可能無法有效避免全部的安全問題,若要進一步挖掘安全問題,還需要借助一些其他測試方法。發現嵌入式系統中的安全問題是一項具有挑戰性的工作,因為嵌入式系統與其他傳統計算機相比,具備體積小、可移植性好、直接與應用程序集成等特點;在運行時,它們占用較少的內存資源和空間,而相應的安全機制占用較多的存儲空間,降低了內存的可利用率。因為在受限的嵌入式系統沒有額外的安全機制,模糊測試技術(Fuzz)作為尋找安全問題最有效的手段之一,一直受到安全測試人員的青睞。在安全程序中使用模糊測試技術可以幫助發現系統中未知的漏洞。對于嵌入式環境下的安全測試,針對二進制文件的模糊測試是十分必要的選擇,此方法可用來排除在編碼過程中出現的大部分安全問題。模糊測試通過向目標插入事先構建的輸入來發現漏洞和故障,對于查找程序問題的效率較高,如內存錯誤、空指針引用、格式化字符串、死鎖、無限循環、不當的資源管理等。如圖2所示,二進制模糊測試一般分為以下5個階段。
圖2 模糊測試一般流程
首先是準備階段,將準備好的被測二進制格式文件進行輸入;其次是模糊數據生成,一般模糊數據生成就是改變特定的數據;接下來將模糊數據作為輸入進行執行和檢測,如果未結束,將回到數據生成階段;周而復始,直至程序崩潰;最后生成報告。
在通過對二進制代碼進行模糊測試的過程中,測試人員可能面臨的難題是在不同的嵌入式環境下系統所產生的不同二進制代碼,如不同的編譯器的代碼生成算法、不同的指令集等,導致安全測試人員難以通過相似性來判斷存在的安全問題。為了克服這種困難,可以借助一些第三方開源模糊器加QEMU等仿真器對嵌入式環境下的二進制代碼進行模糊測試。目前常見的模糊器有以下2種。
(1)American Fuzz Lop
American Fuzz Lop(AFL)是一款基于覆蓋引導的模糊測試工具,其原理是通過記錄輸入樣本的代碼覆蓋率,從而調整輸入樣本以提高覆蓋率,提高發現漏洞的概率,AFL模糊器的工作流程大致如下:
①在編譯階段進行插樁(在每個基本塊的開頭插入一段匯編代碼),用來記錄源碼的覆蓋率;
②選擇輸入文件,作為初始測試集;
③將讀入的文件按照策略進行“變異”(按位反轉、替換邊界等);
④如果文件更新了范圍,將其保留;
⑤在循環以上步驟時,若觸發了crash的文件,將被記錄。
(2)PTFuzzer
PTFuzzer是在AFL的基礎上實現的一款模糊測試工具,它采用了Intel Processor Trace硬件部件來收集程序執行的路徑信息,優化了原來AFL通過編譯插樁方式獲取程序執行路徑信息的方法。由于AFL要Fuzz二進制格式文件,需要借助QEMU的虛擬化支持,在這方面PTFuzzer要優于AFL,但是PTFuzzer需要使用Intel系列芯片的PT支持,造成PTFuzzer有一定的局限性,導致在測試嵌入式軟件時可能需要解決嵌入式軟件的平臺支持問題。
綜合比較以上工具特點,使用QAFL(QEMU與AFL的組合)更適合針對嵌入式軟件進行模糊測試,其原因是使用QAFL的組合不依賴于特定的芯片支持,能夠保證在多變的嵌入式環境下順利進行軟件的模糊測試。
使用二進制Fuzz的方法可以在不依賴程序源碼或者真實運行環境下對嵌入式軟件進行測試,當與其他漏洞檢測方法如使用代碼靜態測試工具、人工審查、逆向工程(通過對二進制文件進行反編譯,分析各個代碼模塊的邏輯內容與調用關系,從而發現嵌入式系統中可能存在的漏洞的一種技術手段)進行比較時,基于二進制的模糊測試可以更高效率地發現諸如緩沖區溢出、內存泄漏、空指針引用、格式化字符串等安全問題。此外,它還具有可以進行大規模測試且無人值守的優勢,因為模糊過程通常是自動化的。模糊測試的技術特點使其漏洞檢測的準確率接近100%,并且可為每個漏洞提供詳細的回溯調試信息,降低運維成本,消除誤報帶來的噪音。但是,由于誤報的原因,在進行模糊測試后,還需手動驗證測試結果以精確定位程序存在的安全問題。
4 結語
本文歸納了嵌入式環境中安全風險較大的幾種常見安全問題,并討論了嵌入式環境下的一些測試方法,主要介紹了靜態測試、動態測試和幾種二進制的模糊測試工具的特點和原理。但是本文提出的測試方法僅僅是處于軟件測試或軟件開發周期的其中一個階段,如果希望嵌入式軟件更為健壯、安全,還需要控制好各個環節,從編碼開發、測試、維護等階段來提高嵌入式軟件的安全性。
(原載于《保密科學技術》雜志2023年2月刊)