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

1、說明

去年寫了一篇「模糊測試(fuzzing)是什麼」,在最後提到能夠本身手動編寫實現模糊測試工具,但一直沒把可行的代碼放上來。html

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

 

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

2.1 如何標識模糊測試項

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

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

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

爲了簡單起見我這裏使用burpsuite的有標識思路,標識標誌是fuzzer_var()。chrome

 

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

以下圖所示中,兩個要測試的位置咱們使用了協定好的fuzzer_var()括了起來,但因爲其原來的值都是admin,因此括起來後他們是同樣的fuzzer_var(admin)。api

這有兩個問題,一是若是在代碼上咱們簡單地將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等使用中間件服務器的場景模糊測試豈不是沒什麼用?實話而言,這種狀況下,是沒什麼用。

 

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

項目語言: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編碼測試載荷
相關文章
相關標籤/搜索