天天看點

模糊測試--六問六答

Fuzz Testing,又稱模糊測試,是一種通過向目标系統提供非預期的“壞資料”輸入并監視異常結果來發現軟體漏洞的方法。

Fuzz Testing,又稱模糊測試,是一種通過向目标系統提供非預期的“壞資料”輸入并監視異常結果來發現軟體漏洞的方法。這句話雖然簡單,實際上可以引申出很多問題,如:

  1. 模糊測試的目标系統有哪些?
  2. 如何生成非預期的“壞資料”?
  3. 如何有效地輸入“壞資料”?
  4. 如何監視異常?
  5. 如何定位觸發異常的輸入?
  6. 如何判斷觸發的輸入可被利用?

接下來,我将就此疑問做出解答,帶大家淺析模糊測試。

  1. 模糊測試的目标系統有哪些?

模式測試的目标有很多,總的來說可以有檔案格式、環境變量、指令行、記憶體、網絡協定、web應用。不僅可以白盒fuzz以驗證目标代碼路徑已滿足,還可以黑盒fuzz以驗證目标系統的健壯性。隻要你願意,萬物皆可Fuzz。

在測試之前,要考慮清楚目标應用程式。拿指令行的模糊測試為例,與其花巨大的精力在普通指令行上,還不如把重點關注在有潛在提權可能的指令上。我們還需要考慮開發商過去被發現的安全漏洞相關曆史,可通過浏覽器安全漏洞收集站點完成,如securityfocus。如果确要選擇目标檔案或庫,應該選擇那些被多個應用程式共享的庫,因為這些庫的使用者群體比較大,出現安全漏洞的風險響應比較高;

在汽車領域,我們更多地關注在網絡協定的模糊測試。衆所周知,車載通信相對複雜,從近場的WiFi、藍牙、USB,到本地的CAN、CANfd、Ether,這些通信媒介上的數十種通信協定都可以成為我們模糊測試的重點。下面的介紹會圍繞通信fuzz展開。

2. 如何生成非預期的“壞資料”

這是模糊測試的靈魂。模糊測試是否能觸發軟體的非預期行為,很大程度上依賴于工具生成的 “壞資料”的品質。一般而言,我們有四種生成“壞資料”的方式:

  • 随機生成:效率最低,沒有任何輸入,依靠fuzz engine随機生成;
  • 根據已知資料結構生成:常用于文本協定,如DoIP、UDS;
  • 基于變異;将現有資料作為種子進行變異,如一個pcap檔案,常用于二進制協定;
  • 基于生成:基于一個特定模型啟發式生成資料;

在vTeststudio中,我們可以基于CAPL實作已知資料結構生成“壞資料”,還可以抓取特定資料包後基于變異生成“壞資料”。編譯好測試用例後,導入CANoe即可進行通信模糊測試。

模糊測試--六問六答

注意:目前模糊測試中“壞資料”都是基于工具以半自動或全自動化生成。

一般而言,“壞資料”不是随意生成的,Fuzz Engine有自己的一套邏輯,但都會有重點考慮:

(1)長串字元:也可以了解為重複字元串,

  • 針對的對象主要是記憶體管理函數、字元串處理函數;
  • 造成的後果為緩沖區溢出,包括棧緩沖區溢出和堆緩沖區溢出。
  • 主要的原因:在沒有額外的檢查下,對輸入字元串處理不當,導緻寫入的資料遠遠大于提前配置設定的空間,是以覆寫那些位于邊界之外的資料;

note1:堆溢出問題對于fuzz來說是個挑戰,因為堆溢出後不一定會像棧溢出那樣立刻彈出非法通路的錯誤,是以不好定位是哪些子串導緻堆溢出;

note2:Windows有全局标志,即GFlags一旦激活該标志,便可以以細粒度的方式跟蹤,記錄與調試軟體的行為,全局調試中就有一個堆調試器,它将記錄下設定的程序下所有的動态記憶體操作,當發現有堆資料遭受污染時,就會産生一個調試事件;設定工具為gflags.exe,也可以在immunity中執行與Gflags綁定的PyCommand指令就可以編輯Gflags标志

(2)整數邊界值:包括大量的高值正整數和低值負整數以及被處理數的整數倍數值。

  • 針對于所有涉及整數處理的函數;
  • 造成的後果為整數值上溢、下溢、符号溢出等,進一步利用後造成緩沖區溢出;
  • 主要的原因:以32位系統為例,在沒有額外的檢查下,當一個操作數的取值超過了32bit,整數就會發生截斷,保留低32位作為資料存儲的結果,這樣就可能導緻預期的資料和實際寫入的資料有很大差異,一旦這些資料涉及到記憶體配置設定,就很有可能造成緩沖區溢出。

常用的資料根據實際應用大概有:0;數字的邊界值,如2^4,2^8,2^16,2^24等,包括其對應的負數和相差為3的整數;将整數替換為浮點數。

(3)格式化字元串:包括格式化串(最好選擇“%s”,“%n”)

  • 造成的後果為記憶體洩漏,進而導緻的系統提權;
  • 主要的問題在于對一類字元串處理不恰當,導緻輸出一些不該輸出的内容。如經常使用的printf函數。我們可以看到spike中內建有13種帶有“%n”參數的值;

note: printf的-n格式符,可以完成對記憶體的寫入,這很有可能給攻擊者提供覆寫函數的傳回位址或重寫某個函數。選擇測試用例時,要格外關注這種能對記憶體讀寫的函數。

(4)字段分隔符(非字母數字字元,如空格、制表符、NULL(0x00)等)和擴充字元(ASCII在128-255的字元,如“{”,“(”,“[”,“(”)

主要的問題是當程式處理這種類型的字元時會有一些特定的行為,如printf會在NULL結束的字元串時停止;

(5)錯誤格式或錯誤内容或錯誤數量的字元串

  • 在一個資料包中将指令打亂,重新組合,字元串解析這種打亂類型的字元串是有時會發生錯誤,如正常情況下string為“pass login”,一旦出現“pass\rlogin\n”字元串将如何處理;
  • 沒有任何意義的錯誤二進制資料可能會觸發未知的錯誤;
  • 連續重複的有意義指令字元串,此時可能會有觸發一些設計或邏輯缺陷;
  • flood攻擊,主要實作DoS;

(6)目錄周遊:如“../”“./”“.”等,車内通信由于不存在檔案系統,是以沒有必要

造成的後果:可以造成某些目錄下的資料洩露;

(7)指令注入:向"exec()"、"system()" 之類的 API 調用傳遞未經過濾的使用者資料;

我們需要注意的是,有時候正常模式下可能無法擷取到特定的資訊,是以可以采取故障注入的方式,讓系統處于特定模式後,重新進行模糊測試,也許會有額外的收獲或者加速系統錯誤和失效的發生。通常可注入的錯誤類型:記憶體錯誤、處理器錯誤、通信錯誤、程序錯誤、消息錯誤、網絡錯誤、程式代碼錯誤等。

3. 如何有效地輸入“壞資料”?

模糊測試并不是注入的“壞資料”越多、越快、越畸形就越好。舉幾個簡單的例子,爆發式的發送“壞資料”,由于目标系統的收發buffer有限,我們輸入的“壞資料”還沒進入應用層,就已經被實體層丢棄;還有,Ether單包長度在64到1518位元組,實際建構單包大于1518或小于64位元組,這類資料包基本會被丢棄。在實際測試中,我們需要結合目标系統的特性,建構合理的“壞資料”,并以合适的速度發送到目标系統。

4. 如何監視異常?

能夠精确地判定目标程式是否發生異常非常的關鍵,可以采取下面方式擷取異常資訊:

  • 通過程式的正常輸出擷取資訊
  • 通過靜态代碼插樁擷取資訊
  • 通過動态二進制插樁擷取資訊
  • 通過虛拟機擷取資訊
  • 通過調試接口或者調試器擷取資訊
  • 與程式建立連接配接,如socket或ping

例如我們可以使用Openocd、Lauterbach等調試工具通過諸如Jtag等調試口檢測晶片異常,再使用Gdb等檢視異常時的堆棧狀态。

模糊測試--六問六答

很多ECU出現異常後會由看門狗自動複位,這會導緻異常不容易被檢測。如果是在開發環境下,建議先關閉看門狗以更好的儲存異常現場。

5. 如何定位觸發異常的輸入?

這是一個好的模糊測試工具的重要考核名額。如何定位觸發異常的輸入考驗了模糊測試工具的可重制性,即測試者必須能夠知道使目标程式狀态變化所對應的測試資料是什麼,如果不具備重制測試結果的能力,那麼整個過程就失去了意義。實作可重制性的一個方法是在發送測試資料的同時記錄下測試資料和目标程式的狀态。

6. 如何判斷觸發異常的輸入可被利用?

判定發現的漏洞是否可能被利用:這種過程是典型的手工過程,需要操作者具有特定的安全知識。學海無涯苦作舟,平時多鍛煉,CTF走一波。

結束語

最後,小編給大家羅列一些模糊測試工具,大多數是開源的,希望未來各位都能成為汽車安全領域的挖洞大拿。

模糊測試--六問六答

内容來源:汽車資訊安全 作者:theoneandone

版權歸原作者所有,如需轉載請聯系作者。

繼續閱讀