模糊測試工具設計思路淺談


一、說明

去年寫了一篇“模糊測試(fuzzing)是什么”,在最后提到可以自己手動編寫實現模糊測試工具,但一直沒把可行的代碼放上來。

其實這不是光說不練沒實現,而是在去年就着手編寫了,並在前段時間發現參數未做防呆處理導致設備重啟上收到了很好的效果,只是一是說代碼涉及產品具體業務需要進行處理二是說對之前做到一半沒做完的事時常缺乏興趣回頭繼續做。

 

二、模糊測試中的幾個關鍵問題討論

2.1 如何標識模糊測試項

標識模糊測試項有兩大思路:一類是sqlmap的無標識思路,另一類是burpsuite的有標識思路。

sqlmap無標識思路:自動分析數據中的參數,然后逐個參數進行測試;優點是使用方便,缺點是如果協議的結構性越差則其參數分析邏輯就要越復雜且不能只測試指定的參數。如sqlmap -d "username=admin&password=abcd1234" -u "http://192.168.1.1/login",此時sqlmap就會分析出username和password兩個參數然后進行測試。

burpsuite的有標識思路:直接使用額外標志標識出要測試的位置;優點是不需要復雜的參數解析代碼能測試指定的位置(不過注意其實burpsuite是有參數分析代碼的),缺點是需要用戶手動標識出要測試的位置當api很多時是一項不小的工作量。在burpsuite的Intruder功能中可以看到各要進行測試的位置使用§符號圍起來。

為了簡單起見我這里使用burpsuite的有標識思路,標識標志是fuzzer_var()。

 

2.2 多個模糊測試項相同有如何處理

如下圖所示中,兩個要測試的位置我們使用了協定好的fuzzer_var()括了起來,但由於其原來的值都是admin,所以括起來后他們是一樣的fuzzer_var(admin)。

這有兩個問題,一是如果在代碼上我們簡單地將fuzzer_var(admin)替換成測試載荷如“AAA”,那么將是用戶名密碼同時被改為"AAA",與我們想要的先用戶名“AAA”,再密碼“AAA”不一致。二是在遍歷時會重復出現用戶名密碼同為“AAA”(因為遍歷到用戶名時用戶名密碼都被改為“AAA”,而遍歷到密碼時又會再次出現用戶名密碼都被改為“AAA”)。

針對這兩個問題我們做改下處理:首先是去重只保留一個如fuzzer_var(admin);其次是遍歷api中的所有fuzzer_var(admin)。去重好理解,但遍歷是如何遍歷法呢?分三步,第一步是將已遍歷過的還原為原始值,二是將遍歷到的替換成測試載荷,三是將剩下的與去其fuzzer_var()一起去除。具體可見fuzzer.py中的send_payload()。

 

2.3 時序性協議處理

時序性協議有兩重含義,一是指后邊的請求需要使用前邊請求的響應值,如B請求需要A響應的內容而C請求又需要B響應的內容;二是指請求是有強制的先后順序的,比如一定要先完成A請求然后再完成B請求最后才能進行C請求,直接發送C請求服務器是不處理的。

針對這種情況,較之普通的模糊測試我們需要多兩道處理程序:一是每個api需要使用一個函數去動態生成而不能直接寫在api文件里邊了;二是在測試后邊請求時一定要確保前邊請求都已正確通過不然請求不能有效測試。

時序性協議我這里使用rtsp協議進行演示,可以看到每個api都是使用一個gen_xxx_header()函數來生成。

 

2.4 二進制協議處理

前面說的http和rtsp協議可以稱為是字符串的,但有些協議是二進制的;二進制的就意味着在接收到數據包時,一是服務端只會接收協議結構限制的長度(如果真做得很粗糙也不一定但至少說很容易限制長度),二是服務端對於接收到的數據只會按協議的結構去解析(比如一個字段是一個字節就是一個字節你構造一個超長字符串沒用只是擠占掉后邊的字段)。

所以對於二進制協議一般的模糊測試載荷是沒有很大意義的,可行的思路是根據協議針對各個字段,在字段長度范圍內構造攻擊載荷。比如一個字段只有半個字節(4 bit)那么就遍歷0到f,一個字段只有一個字節那你可以遍歷00到ff,如果一個字段兩字節那么就先外邊for一個字節里邊for一個字節。

這比較麻煩,我這里以snmp為例,但只是偷懶地認為一個字節一個字段的進行測試(即逐個字節遍歷00到ff),以后如果再研究再寫個規范的。

 

2.5 返回值監測問題

應當來講在C語言時代,不管是文件模糊測試還是瀏覽器模糊測試還是網絡協議模糊測試,認為有bug的標志都是處理程序崩潰,這種崩潰使用代碼判斷是比較麻煩的,比如一個請求發出去服務器沒響應那怎么判斷是網絡不通還是服務器崩潰了?如果是服務器崩潰了那怎么恢復環境進行后續項測試?

總而言之最開始的模糊測試,以人觀察到程序崩潰為標志是不需要模糊測試工具監測和分析返回值的,是半自動化而非會自動化的。我這里也不監測分析服務端響應。

而人們中了自動化的毒,希望整個流程都是自動化的,一定要全自動化那唯一的思路就是監測分析服務端響應並約定一些判定標准和制定一些恢復機制;而且監測分析返回值我偏向於認為那是掃描器的事。

當前Java等語言實現的服務端,出錯也只是頁面出錯,中間件進程一般是不會崩潰的,又不監測分析服務端響應,那對於Java等使用中間件服務器的場景模糊測試豈不是沒什么用?實話而言,這種情況下,是沒什么用。

 

三、模糊測試工具具體實現

項目語言:Python3

依賴安裝:pip install requests selenium scapy

github地址:https://github.com/PrettyUp/Fuzzer

項目目錄結構及文件說明如下:

|
|--apis----模糊測試配置及api文件存放目錄
|    |--api.ini----fuzzer.py默認使用的配置及api文件,一般修改該文件即可測試自己的IP和協議
|
|--common----公共文件存放文件夾
|    |--logger.py----自定義日志配置程序
|    |--login.py----fuzzer.py使用的登錄程序,需要根據自己系統登錄邏輯修改該文件
|
|--fuzzers----模糊測試工具存放目錄
|    |--chromedriver.exe----chrome驅動程序
|    |--geckodriver.exe----firefox驅動程序
|    |--geckodriver.log----geckodriver.exe自己生成的日志文件
|    |--fuzzer.py----一般性的模糊測試工具模板,一般稍加修改即可用來測試自己的api(如token插入位置等);修改api.ini直接python fuzzer.py運行即可
|    |--rtsp_fuzzer.py----rtsp協議模糊測試工具,時序性協議示例;修改其中的config_dict,直接python rtsp_fuzzer.py運行即可
|    |--snmp_fuzzer.py----snmp協議模糊測試工具,二進制協議示例,半成品;修改其中的config,直接python snmp_fuzzer.py運行即可
|
|--logs----模糊測試日志存放目錄
|    |--nvr_2019-06-03.log----nvr是自定義的日志前輟,2019-06-03是當前日期,.log是日志固定后輟
|
|--payloads----各類型模糊測試載荷文件存放目錄
     |--format_string.txt----格式化字符串測試載荷
     |--overflow.txt----緩沖區溢出測試載荷,使用了python的"A"*count語法
     |--random_num.txt----整數溢出測試載荷
     |--special_char.txt----特殊字符測試載荷
     |--unicode.txt----unicode編碼測試載荷

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM