強大的模糊測試工具 go-fuzz
推薦 go-fuzz 的背景
我們在日常開發中經常會編寫測試和對應的測試用例,大家是否常常會有以下疑惑:
- 現有的測試用例是否完全覆蓋了各種邊界場景?會不會有意料之外的 case?
- 程式碼測試覆蓋率都達到 100% 了,程式碼上線時為啥還會戰戰兢兢?
- 寫測試用例太費心費力了,有沒有一款能自動生成測試用例的工具?
這次要推薦給大家的 go-fuzz
也許能讓你的工程魯棒性再上一個臺階,並或多或少緩解你的擔憂。
go-fuzz
(https://github.com/dvyukov/go-fuzz)是 Dmitry Vyukov 大神早在 go1.5 時代開源(Apache License 2.0 開源許可)的一款 golang 模糊測試工具,為解析複雜輸入(文字或二進位制)的系統提供了強大的魯棒性驗證手段。迄今為止,go-fuzz
已經為 go 語言(你沒看錯,就是 golang 自身)和一些三方庫檢測出了幾百個缺陷,可謂居功至偉!
go-fuzz 與模糊測試
維基百科對模糊測試的解釋如下:
模糊測試(fuzz testing, fuzzing)是一種軟體測試技術。其核心思想是將自動或半自動生成的隨機資料輸入到一個程式中,並監視程式異常,如崩潰,斷言(assertion)失敗,以發現可能的程式錯誤,比如記憶體洩漏。模糊測試常常用於檢測軟體或計算機系統的安全漏洞。
go-fuzz
自動生成的測試用例可不是簡單的隨機,它強依賴於 afl
(American Fuzzy Lop),在執行時會根據程式現有的用例和用例執行情況按照一定的演算法規則進行迭代修改,從而無限 “裂變” 生成新測試。
目前 gitlab.com 和 fuzzbuzz.io 上均有基於 go-fuzz
的 ci 整合。
go-fuzz 應用舉例
下面我們就以 fuzzbuzz.io 上的小例子來看 go-fuzz 如何使用。如下程式碼中有一處比較隱晦的 bug,當輸入的 Data
剛好是 FUZ
時會觸發訪問越界:
package tutorial
// BrokenMethod has a bug - it will try to read the 4th
// index of Data even when it only has a length of 3.
func BrokenMethod(Data string) bool {
return len(Data) >= 3 &&
Data[0] == 'F' &&
Data[1] == 'U' &&
Data[2] == 'Z' &&
Data[3] == 'Z'
}
接下來我們嘗試使用 go-fuzz
對漏洞進行探測
Step0: 安裝 go-fuzz-build
和 go-fuzz
go get -u github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest
別忘了把 $GOPATH/bin 新增到 PATH 中
Step1: 編寫測試函式
在程式碼中新增 method_fuzz.go,注意 // +build gofuzz
是必須新增的,接下來的構建步驟會對其進行識別。
// +build gofuzz
package tutorial
func Fuzz(data []byte) int {
BrokenMethod(string(data))
return 0
}
Fuzz
函式的返回碼目前有 3 個可選值:返回1
表示當前的輸入權重增加,返回-1
表示當前的輸入不新增進語料庫,否則返回0
。
Step2: 設計幾個初始語料
我們新增 F
和 FU
作為 BrokenMethod
的兩個測試用例。當然,如果你的程式碼中有一些已經設計好的用例,也可以直接複製到 workdir/corpus
下。
mkdir -p workdir/corpus
echo -n "F" >workdir/corpus/1
echo -n "FU" >workdir/corpus/2
新增初始語料不是必須的,但是
go-fuzz
作者建議初始語料越豐富越好,這對後續的模糊測試執行很有幫助!
Step3: go-fuzz-build
生成測試工程
go get -d github.com/dvyukov/go-fuzz-corpus
go-fuzz-build
這一步可能需要花一些時間,這跟工程的複雜度有關係。執行成功後,會在當前目錄裡看到一個 tutorial-fuzz.zip
的壓縮包。
go-fuzz
是 go1.5 時期的老傢伙了,當前對 go module 的支援還處於早期階段。構建測試前執行go get -d github.com/dvyukov/go-fuzz-corpus
會在 go.mod 裡新增一行並不需要的依賴,模糊測試執行完畢後使用 go mod tidy 即可恢復。
Step4: go-fuzz
執行模糊測試
go-fuzz -bin=tutorial-fuzz.zip -workdir=workdir
這時我們看到控制檯有如下輸出:
2021/05/16 13:56:45 workers: 4, corpus: 4 (2s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 3s
2021/05/16 13:56:48 workers: 4, corpus: 4 (5s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 6, uptime: 6s
2021/05/16 13:56:51 workers: 4, corpus: 4 (8s ago), crashers: 1, restarts: 1/408, execs: 48969 (5440/sec), cover: 6, uptime: 9s
...
go-fuzz
執行測試時不會自動終止,當我們發現 crashers 欄位的值不為 0 時(有用例觸發了程式異常),就可以終止測試並檢視測試結果了,導致程式異常的用例會存放在 workdir/crashers/ 目錄中
Step5: 分析測試結果
$ tree workdir/crashers/
workdir/crashers
├── 0eb8e4ed029b774d80f2b66408203801cb982a60
├── 0eb8e4ed029b774d80f2b66408203801cb982a60.output
└── 0eb8e4ed029b774d80f2b66408203801cb982a60.quoted
可見,workdir/crashers
中多出了 3 個檔案,它們的檔名均為輸入用例的 sha1sum 值。
- 不帶字尾的檔案存放用例的原始輸入
- 字尾
.quoted
的檔案存放字串形式的用例輸入(方便貼入程式碼直接進行除錯,設計太友好了)- 字尾為
.output
的檔案存放異常時的錯誤輸出
$ cat workdir/crashers/0eb8e4ed029b774d80f2b66408203801cb982a60.quoted
"FUZ"
$ cat workdir/crashers/0eb8e4ed029b774d80f2b66408203801cb982a60.output
panic: runtime error: index out of range [3] with length 3
goroutine 1 [running]:
demo.BrokenMethod.func4(...)
/Users/blanet/repos/tmp/tutorial-go/method.go:9
demo.BrokenMethod(0xc000092e80, 0x3, 0x3)
/Users/blanet/repos/tmp/tutorial-go/method.go:10 +0x11d
demo.Fuzz(0x4810000, 0x3, 0x3, 0x3)
/Users/blanet/repos/tmp/tutorial-go/fuzz.go:5 +0x6f
go-fuzz-dep.Main(0xc000092f70, 0x1, 0x1)
go-fuzz-dep/main.go:36 +0x1b8
main.main()
demo/go.fuzz.main/main.go:15 +0x52
exit status 2
至此,我們找到了程式中的漏洞以及復現漏洞的用例,稍加除錯問題就迎刃而解了!漏洞修復後,我們還可以為找到的 bad case 設計新的單元測試,進一步提升程式碼質量。
總結
使用 go-fuzz
可以為程式整合模糊測試,對於檢測複雜輸入系統的魯棒性、篩查各種深水區 panic
的場景非常有幫助。大家趕快試用吧!
參考資料
- https://github.com/dvyukov/go-fuzz
- https://go-talks.appspot.com/github.com/dvyukov/go-fuzz/slides/go-fuzz.slide
- https://www.youtube.com/watch?v=a9xrxRsIbSU&t=459s
- https://github.com/google/gofuzz
- https://en.wikipedia.org/wiki/Fuzzing
- https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/
- https://about.gitlab.com/blog/2020/12/03/how-to-fuzz-go/
- https://docs.fuzzbuzz.io/getting-started/find-your-first-bug-in-go
- https://medium.com/@dgryski/go-fuzz-github-com-arolek-ase-3c74d5a3150c
歡迎加入 GOLANG 中國社群:https://gocn.vip
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 模糊測試工具Simple Fuzzer
- Web模糊測試工具PowerfuzzerWeb
- 12個強大的Web服務測試工具Web
- 網站模糊測試爆破工具Wfuzz網站
- Firefox 10 測試版擁有更強大的Web開發工具FirefoxWeb
- JavaScrip模糊測試(開題)Java
- [Fuzz]Android模糊測試Android
- 10大主流壓力測試工具
- 官方教程:Go fuzzing模糊測試Go
- 模糊測試: 初學者入門指南
- 大資料測試學習筆記之測試工具集大資料筆記
- 強大的 Guava 工具類Guava
- Backtrack5下WEB模糊測試Web
- 強大的系統硬體監測工具iStat Menus
- 基於Java的四大開源測試工具Java
- 富文字儲存型XSS的模糊測試之道
- [測試工具]
- GoFrame - 強大的工具鏈集合GoFrame
- 10大主流壓力測試工具推薦
- 軟體測試培訓:不可不知的十大軟體測試工具
- 幹掉 BeanUtils!試試這款 Bean 自動對映工具,真心強大!Bean
- 軟體測試常用的工具都有哪些-測試常用工具
- 十大搶手的網站壓力測試工具網站
- 鴻蒙 OS 的測試工具鴻蒙
- 效能測試工具的原理
- Fuzzm: 針對WebAssembly記憶體錯誤的模糊測試Web記憶體
- 越來越強大的SAFS/STAF/STAX自動化測試框架框架
- Java開源軟體測試工具大彙總Java
- 方正銳圖:強大的分色工具
- Windows下強大的同步工具 - robocopyWindows
- 介面測試工具
- 安全測試工具
- 【DNS】測試工具DNS
- 測試工具集合
- 效能測試工具
- Jmeter測試工具的實際專案測試案例JMeter
- 測試管理及測試工具盒集
- 軟體測試工具之開源測試工具彙總