七叶笔记 » golang编程 » Golang fuzzy测试

Golang fuzzy测试

在软件测试领域和安全测试方面目前有一个比较活跃和快速增长的领域那就是fuzzy 模糊测试。从 Go 1.18 开始,Golang在其标准工具链中开始支持fuzzy测试。

概述

Fuzzing 是一种自动化测试,通知自动配置程序的输入,来来测试代码中潜在的问题,比如panics、bug或数据顺序问题等。这些半随机数据变化可以发现现有单元测试可能遗漏的新代码覆盖率,并发现否则会被忽视的边界情况错误。当能够快速运行更多参数突变时,这种类型的测试效果最好。

由于fuzzy测试可以检测人类经常错过的边缘情况,因此fuzzy测试对于发现安全问题和漏洞特别有用。fuzzy测试目前主要由 安全工程师 编写,黑客可能会使用类似的方法来恶意查找漏洞。但是,编写模糊测试不必局限于具有安全专业知识的开发人员。对所有程序进行fuzzy测试都有很大的价值,包括那些可能与安全相关的更微妙的程序,尤其是那些处理任意用户输入的程序。

现代语言通过一定方式支持或者建议使用fuzzy测试。其中libFuzzer和AFL是被被广泛使用的fuzzy框架。在C/C++ 中,AFL已经发现了诸如 Mozilla Firefox、 Internet Explorer OpenSSH 、Adobe Flash 等程序中的漏洞。 在 Rust 中,其内置的工具car go -fuzz 除了原始字节外还允许对结构化数据进行模糊测试,从而为编写模糊测试提供更大的灵活性。在Golang 1.18开始,在其标准工具链中支持fuzzy测试。

编写

一个典型的fuzzy测试的例子如下:

编写fuzzy测试必须遵循的规则一下规则:

fuzzy测试必须是一个名为的函数FuzzXxx,函数只接受一个*testing.F参数,无返回值。

fuzzy测试的 测试用例 都必须在*_test.go文件中才能运行。

一个fuzzy的目标必须是一个(*testing.F).Fuzz方法调用,第一参数为 *testing.T,然后是fuzzy测试的参数。该调用无返回值。

每个fuzzy测试必须正好有一个fuzzy目标。

所有种子语料库条目必须具有以下类型与fuzzy参数相同,顺序相同。这适用于调用 (*testing.F).Add和任何fuzzy测试的testdata/fuzz目录中的语料库文件。

fuzzing 参数只能是以下类型:

 string, [] byte 
int, int8, int16, int32/rune, int64
uint, uint8/byte, uint16, uint32, uint64
float32, float64
 bool   

fuzzy测试应该在支持覆盖检测的平台上运行(目前是AMD64和ARM64)以便语料库可以有意义地增长运行,并且在fuzzy测试时可以覆盖更多代码。

fuzzy目标应该是快速和确定的,这样fuzzy引擎才能高效工作,并且可以轻松重现新的故障和代码覆盖率。

fuzz目标是跨多个工作线程并行调用的,并且在非确定性顺序,fuzzy目标的状态不应该持续过去每次调用结束,fuzzy目标的行为不应该依赖于全局状态。

运行

默认的go命令设置应该适用于大多数fuzzy测试用例。在go命令行以下面的格式执行fuzzy测试:

 go test -fuzz={FuzzTestName}  

go命令在运行fuzzy测试时启用一些设置。这些记录在cmd/go打包文档。

强调几个:

-fuzztime: fuzz 目标的总时间或迭代次数 退出前会执行,默认无限期执行。

-fuzzminimizetime:fuzzy目标的时间或迭代次数 将在每次最小化尝试期间执行,默认为60秒。 你可以 通过设置完全禁用最小化 -fuzzminimizetime 0fuzzy时。

-parallel:一次运行的fuzzy测试进程数,默认 $GOMAXPROCS. 目前,在fuzzy测试期间设置 -cpu 无效。

测试结果类似下面截图。

相关文章