2006 年 11 月 02 日
模糊測試(Fuzz testing )是一項對代碼質量有著深遠影響的簡單技術。在本文中,Elliotte Rusty Harold 故意將隨機的壞數據插入應用程序,以觀察發生的結果。他也解釋了如何使用如校驗和、xml 數據存儲及代碼驗證等防護性編碼技術,來加固您的程序以抵制隨機數據。他以一個練習進行總結,在練習中他以一個代碼破壞者的角度進行思考 —— 這是一種用于防護代碼的至關重要的技術。
多年來,我贊嘆于有如此大量能夠使 Microsoft Word 崩潰的壞文件。少數字節錯位,會使整個應用程序毀于一旦。在舊式的、無內存保護的操作系統中,整個計算機通常就這樣宕掉了。Word 為什么不能意識到它接收到了壞的數據,并發出一條錯誤信息呢?為什么它會僅僅因為少數字節被損壞就破壞自己的棧、堆呢?當然,Word 并不是惟一一個面對畸形文件時表現得如此糟糕的程序。
本文介紹了一種試圖避免這種災難的技術。在模糊測試中,用隨機壞數據(也稱做 fuzz)攻擊一個程序,然后等著觀察哪里遭到了破壞。模糊測試的技巧在于,它是不符合邏輯的:自動模糊測試不去猜測哪個數據會導致破壞(就像人工測試員那樣),而是將盡可能多的雜亂數據投入程序中。由這個測試驗證過的失敗模式通常對程序員來說是個徹底的震憾,因為任何按邏輯思考的人都不會想到這種失敗。
模糊測試是一項簡單的技術,但它卻能揭示出程序中的重要 bug。它能夠驗證出現實世界中的錯誤模式并在您的軟件發貨前對潛在的應當被堵塞的攻擊渠道進行提示。
模糊測試如何運行
模糊測試的實現是一個非常簡單的過程:
可以用任意多種方式改變該隨機數據。例如,可以將整個文件打亂,而不是僅替換其中的一部分,也可以將該文件限制為 ASCII 文本或非零字節。不管用什么方式進行分割,要害是將大量隨機數據放入應用程序并觀察出故障的是什么。
可以手動進行初始化測試,但要想達到最佳的效果則確實需要采用自動化模糊測試。在這種情況下,當面臨破壞輸入時首先需要為應用程序定義適當的錯誤行為。(假如當輸入數據被破壞時,您發現程序正常運行,且未定義發生的事件,那么這就是第一個 bug。)隨后將隨機數據傳遞到程序中直到找到了一個文件,該文件不會觸發適當的錯誤對話框、消息、異常,等等。存儲并記錄該文件,這樣就能在稍后重現該問題。如此重復。
盡管模糊測試通常需要一些手動編碼,但還有一些工具能提供幫助。例如,清單 1 顯示了一個簡單的 java™ 類,該類隨機更改文件的特定長度。我常愿意在開始的幾個字節后面啟動模糊測試,因為程序似乎更可能注重到早期的錯誤而不是后面的錯誤。(您的目的是想找到程序未檢測到的錯誤,而不是尋找已經檢測到的。)
import java.io.*;import java.security.SecureRandom;import java.util.Random;public class Fuzzer { PRivate Random random = new SecureRandom(); private int count = 1; public File fuzz(File in, int start, int length) throws IOException { byte[] data = new byte[(int) in.length()]; DataInputStream din = new DataInputStream(new FileInputStream(in)); din.readFully(data); fuzz(data, start, length); String name = "fuzz_" + count + "_" + in.getName(); File fout = new File(name); FileOutputStream out = new FileOutputStream(fout); out.write(data); out.close(); din.close(); count++; return fout; } // Modifies byte array in place public void fuzz(byte[] in, int start, int length) { byte[] fuzz = new byte[length]; random.nextBytes(fuzz); System.arraycopy(fuzz, 0, in, start, fuzz.length); } } 新聞熱點
疑難解答