Go Fuzzing:发现你未曾发现的漏洞

news2025/1/10 20:40:40

文章目录

  • Fuzzing(模糊测试)
  • 要求
  • 示例
    • 模拟crash
  • 总结
  • 参考资料

Fuzzing(模糊测试)

go fuzz文档

对于软件开发者而言,一项重要的任务就是确保程序的安全性。而其中一种风险就是软件中可能存在的漏洞。传统的测试方法往往需要耗费大量的时间和人力,而使用Fuzzing技术则可在短时间内大规模发现潜在的漏洞。

那什么是Fuzzing技术呢?简单说,它就是让程序自动生成大量随机的输入数据,然后运行被测试的程序,观察是否会出现异常行为。通过这种方式,Fuzzing技术可以快速发现和定位程序中的漏洞,帮助开发者提高程序的安全性。

那在Go语言中,如何使用Fuzzing技术呢?下面就让我们一起来了解一下。

Fuzzing,又叫fuzz testing,中文叫做模糊测试或随机测试。其本质上是一种自动化测试技术,更具体一点,它是一种基于随机输入的自动化测试技术,常被用于发现处理用户输入的代码中存在的bug和问题。

在具体实现上,Fuzzing不需要像单元测试那样使用预先定义好的数据集作为程序输入,而是会通过数据构造引擎自行构造或基于开发人员提供的初始数据构造一些随机数据,并作为输入提供给我们的程序,然后监测程序是否出现panic、断言失败、无限循环等。这些构造出来的随机数据被称为语料(corpus)。另外Fuzz testing不是一次性执行的测试,如果不限制执行次数和执行时间,Fuzz testing会一直执行下去,因此它也是一种持续测试的技术。

Fuzzing是对其他形式的测试、代码审查和静态分析的补充,它通过生成一个有趣的输入语料库,而这些输入几乎不可能用手去想去写出来,因此极易被传统类型的测试所遗漏。Fuzzing可以帮助开发人员发现难以发现的稳定性、逻辑性甚至是安全性方面的错误,特别是当被测系统变得更加复杂时。

Go 1.18版本正式接受了原生支持Fuzzing这个特性,Fuzzing成为Go的“一等公民”。

要求

Go Fuzz结构如图:

image

模糊测试必须遵循下⾯的规则:

  1. 模糊测试函数名必须是 FuzzXxx ,参数是 *testing.F ,没返回值 ,如 func FuzzXxx(f
    *testing.F)

  2. 模糊测试必须放在以 *_test.go 后缀的⽂件中

  3. fuzz target 必须是调⽤ (*testing.F).Fuzz ,第⼀个参数 *testing.T , 后⾯是模糊测试的参数

  4. ⼀个模糊测试只能有⼀个fuzz target

  5. 种⼦语料(seed corpus )的数据类型必须和 fuzzing arguments⼀样,顺序⼀致。包括调⽤ (*testing.F).Add 增加种⼦语料,以及写在testdata/fuzz⽂件夹下语料
    fuzzing arguments 只能是下⾯的类型。如果你要测试复杂的struct,需要使⽤这些参数组装你的struct,然后进⼀步测试:

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

示例

下面我们使用Fuzz对DNP3协议进行测试

func FuzzDnp3(f *testing.F) {
	f.Add([]byte{
		0x05, 0x64, 0x20, 0x44, 0x03, 0x00, 0x04, 0x00, 0x95, 0xe3, 0x85, 0x00, 0x01, 0x00, 0x00, 0x00,
		0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xef, 0xdc, 0x00, 0x01, 0x00, 0x00,
		0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x1f,
	})
	f.Fuzz(func(t *testing.T, data []byte) {
		Decode(data)
	})
}

可以使用命令运行

go test -v -fuzz  .

在Goland中也可以直接运行点击函数旁边的运行符号选择Fuzz进行运行,

D:\dev\Go\go1.20.1\bin\go.exe test -json app_go/pkg/dnp3 -fuzz ^\QFuzzDnp3\E$ -run ^$ #gosetup
kg/dnp3"}
=== RUN   FuzzDnp3
fuzz: elapsed: 0s, gathering baseline coverage: 0/23 completed
fuzz: elapsed: 0s, gathering baseline coverage: 23/23 completed, now fuzzing with 8 workers
fuzz: elapsed: 3s, execs: 99037 (32828/sec), new interesting: 1 (total: 24)
fuzz: elapsed: 6s, execs: 133383 (11479/sec), new interesting: 1 (total: 24)
fuzz: elapsed: 8s, execs: 133383 (0/sec), new interesting: 1 (total: 24)
--- PASS: FuzzDnp3 (8.02s)
PASS
ok  	app_go/pkg/dnp3	8.530s

fuzz testing默认会一直执行下去,直到遇到crash。如果要限制fuzz testing的执行时间,可以使用-fuzztime,比如下面的命令允许fuzz testing只执行10

go test -v  -fuzztime 10s -fuzz .

在上面fuzz执行过程中,Go fuzzing会将其缓存在cache路径下:

image

go fuzzing会为每个FuzzXxx函数建立对应的语料缓存。目前fuzz cache的默认路径为$GOCACHE/fuzz/包路径/FuzzXxx,后续可能会提供环境变量或cmd option,以允许开发人员自定义fuzzing语料的缓存路径。

fuzzing test默认会一直执行下去,如果不限制执行次数和执行时间,执行Fuzzing test的机器要有足够的存储才行。而要想清理过多的fuzz缓存,用gotip clean -cache是不行的,需要为clean加上**-fuzzcache**才可以清除fuzz的cache。

模拟crash

当我们在代码中模拟一个crash的产生来看看:fuzzing test过程中发现代码bug时

我们看到go fuzzing在执行测试时就发生crash,fuzzing将crash输出了crash报告,并将引发这一crash的语料放入了testdata/fuzz/FuzzSubmit目录下:

image

=== RUN   FuzzDnp3
fuzz: elapsed: 0s, gathering baseline coverage: 0/24 completed
failure while testing seed corpus entry: FuzzDnp3/seed#13
fuzz: elapsed: 0s, gathering baseline coverage: 12/24 completed
--- FAIL: FuzzDnp3 (0.22s)
    --- FAIL: FuzzDnp3 (0.00s)
        testing.go:1485: panic: interface conversion: cache.Value is nil, not *dnp3.DNP3
            goroutine 28 [running]:
            runtime/debug.Stack()
            	D:/dev/Go/go1.20.1/src/runtime/debug/stack.go:24 +0x9e
            testing.tRunner.func1()
            	D:/dev/Go/go1.20.1/src/testing/testing.go:1485 +0x1f6
            panic({0xec5240, 0xc0001149c0})
            	D:/dev/Go/go1.20.1/src/runtime/panic.go:884 +0x213
            app_go/pkg/dnp3.Decode({0xc00017e140, 0x124, 0x140})
            	D:/workspace/project/**/pkg/dnp3/dnp3.go:137 +0xf49
            app_go/pkg/dnp3.FuzzDnp3.func1(0x0?, {0xc00017e140?, 0x0?, 0xc182f9?})
            	D:/workspace/project/**/pkg/dnp3/dnp3_test.go:254 +0x45
            reflect.Value.call({0xeba2c0?, 0xf2f248?, 0xbff076?}, {0xf00b82, 0x4}, {0xc000114960, 0x2, 0x2?})
            	D:/dev/Go/go1.20.1/src/reflect/value.go:586 +0xb07
            reflect.Value.Call({0xeba2c0?, 0xf2f248?, 0x107dd00?}, {0xc000114960?, 0xf00080?, 0xc000112678?})
            	D:/dev/Go/go1.20.1/src/reflect/value.go:370 +0xbc
            testing.(*F).Fuzz.func1.1(0x0?)
            	D:/dev/Go/go1.20.1/src/testing/fuzz.go:335 +0x3f3
            testing.tRunner(0xc0001249c0, 0xc00012a630)
            	D:/dev/Go/go1.20.1/src/testing/testing.go:1576 +0x10b
            created by testing.(*F).Fuzz.func1
            	D:/dev/Go/go1.20.1/src/testing/fuzz.go:322 +0x5b9
        
  

FAIL
exit status 1
FAIL	**/dnp3	0.597s

进程 已完成,退出代码为 1


如果是真实的fuzz测试引发了crash,我们可以将该语料提取出来,建立针对它的TestXxx或为现有TestXxx添加一条测试数据来验证目标方法是否真实存在缺陷,如果的确存在缺陷,我们就需要修复它,并在修复后再次运行TestXxx,以保证我们的修复是有效的。

总结

Go fuzzing正式成为Go的“一等公民”,Go原生支持Fuzzing。我们可以利用fuzzing发现bug和安全问题。

参考资料

  1. fuzz-beta
  2. go.dev/doc/tutorial/fuzz
  3. fuzz

推荐一个零声学院免费教程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/457795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++: 模块二 ---运算符、流程控制语句】

C: 模块二 ---运算符、流程控制语句 一、运算符:1.1算数运算符:1.2赋值运算符:1.3比较运算符:1.4逻辑运算符:1.5三目运算符: 二、程序流程结构2.1顺序结构:2.2选择结构:&…

ChatGPT免费第一版本

最近利用空余时间做了一个供大家免费体验的chatgpt国内可直接访问的版本 输入12345gpt.com可直接访问 贴上GPT给我回复的内容,😀 当今社会,交流已经成为人们日常不可或缺的一部分。然而,随着技术的发展,人们对于交流工…

【Linux 裸机篇(七)】I.MX6U 中断系统

目录 一、中断向量表1. 中断向量偏移 二、中断系统简介1. 创建中断向量表 三、GIC 控制器简介1. 中断 ID 四、GIC 逻辑分块1. Distributor(分发器端)2. CPU Interface(CPU 接口端) 五、CP15 协处理器六、中断使能1. IRQ 和 FIQ 总中断使能2. ID0~ID1019 中断使能和禁止 七、中断…

【PXE高效的批量网络装机】

目录 一、PXE的概述1.1、PXE批量部署的优点1.2、搭建PXE满足的以下的前提条件1.3、搭建PXE远程安装 二、搭建PXE远程安装服务器1、安装并启动 TFTP 服务2、安装并启用 DHCP 服务3、准备 Linux 内核、初始化镜像文件4、准备PXE 引导程序5、安装FTP服务,准备CentOS 7 …

SpringMVC使用域对象共享数据

1、SpringMVC中的域对象 此处只有request、session、servletContext被使用,而page是jsp页面的域,不使用jsp。 request:一次请求的范围内session:一次会话的范围内servletContext:整个web的应用范围内 2、向request域…

MySQL高级第十七篇:数据库主从复制原理及保证数据一致性

MySQL高级第十七篇:数据库主从复制原理及保证数据一致性 一、概述1. 提升数据库的并发能力2. 主从复制的作用? 二、主从复制原理三、搭建一主一从环境四、如何解决数据一致性问题?1. 方案一、异步复制2. 方案二、半同步复制3. 方案三、组复制…

3.黑马Springboot原理篇自己修改笔记

原理篇 1.自动配置的工作流程 1.1 bean的加载方式 方式一&#xff1a;配置文件<bean/>标签 缺点&#xff1a;配置bean太繁琐 方式二&#xff1a;配置文件扫描注解定义bean⭐️ 获取bean方式 ①通过配置文件&#xff0c;扫描指定包&#xff0c;加载bean ②通过注解声…

C++ STL之string容器的模拟实现

目录 一、经典的string类问题 1.出现的问题 2.浅拷贝 3.深拷贝 二、string类的模拟实现 1.传统版的string类 2.现代版的string类&#xff08;采用移动语义&#xff09; 3.相关习题* 习题一 习题二 4.写时拷贝 5.完整版string类的模拟实现[注意重定义] MyString.h…

磁珠的工作原理

磁珠是一个耗能元器件&#xff0c;他能把频率相对较高的信号以热量的形式耗散掉&#xff0c;保留频率相对较低的信号。 主要有这种插件的磁珠&#xff0c;还有这种贴片的磁珠。 下面我们来看下磁珠具体工作原理。 磁珠的构造我们可以简单的看成一个导线穿过环形铁氧体的磁性材…

[渗透教程]-015-网络与系统渗透

文章目录 1.0基本概念2.0 网络与系统渗透基本原理2.1 渗透测试2.2 入侵和预防2.3 案例一:从信息收集到入侵提权2.3.1 从域名到ip2.3.2 从IP获取旁站2.3.3 收集系统与⽹络配置详细信息2.3.4 踩点2.3.5发现漏洞2.3.6漏洞利用2.3.7维持系统控制权2.3.8清理访问痕迹2.4 案例二:Goo…

TryHackMe-Jeff(boot2root | Hard?)

Jeff 你能破解杰夫的网络服务器吗&#xff1f; 如果你发现自己在暴力破解SSH&#xff0c;你就做错了。 端口扫描 循例nmap 进80&#xff0c;是一个空页面&#xff0c;查看源代码 将jeff.thm加入hosts 上gobuster /admin是空页面&#xff0c;/backups也没东西&#xff0c;/up…

Centos安全加固策略

目录 密码安全策略 设置密码的有效期和最小长度 设置用户密码的复杂度 登录安全策略 设置用户远程登录的安全策略 安全的远程管理方式 访问控制 限制root用户登录 修改ssh 22端口 设置登录超时时间 限制IP访问 安全审计 审核策略开启 日志属性设置 查看系统登录…

基础巩固、探寻Java装箱和拆箱的奥妙!

前言 今天在逛某知名论坛的时候&#xff0c;看到一篇"请不要使用包装类型&#xff0c;避免造成性能损失"的文章。一下子就吸引了我的注意。大意就是&#xff0c;能用基本数据类型就尽量用基本数据类型&#xff0c;因为包装类型自动拆箱、装箱会带来性能损失尤其是循环…

函数式编程#3纯函数的概念

纯函数的概念 文章目录 纯函数的概念纯函数的两种形式&#xff1a;调用目标本身,不会改变函数内部,不受函数外部影响 函数的副作用如何理解"相同的输入得到相同的输出"不是纯函数的映射关系是纯函数的映射关系 纯函数的两种形式&#xff1a; 调用目标本身,不会改变 …

gcc编译 与交叉编译(x86 to arm) (一)单个文件编译

1.1、gcc编译单个c程序&#xff08;hello.c) gcc hello.c -o hello (hello是生成的可执行程序的名字&#xff09;1.2、交叉编译hello.c 源平台&#xff1a; UOS_X86_64 目标平台&#xff1a;UOS_arm 方法&#xff1a;使用现成的交叉编译工具链 参考资料&#xff1a;交叉编译…

【UE】water插件的简单使用

UE Editor版本&#xff1a;4.26 目录 一、岛屿外观修改 二、波浪参数设置 三、水体海洋的颜色设置 四、 水体河流 五、创建可浮在水体上的actor 一、岛屿外观修改 1. 保证“Landmass”和“Water”插件已启用 启用后&#xff0c;搜索water可以看到如下组件 2. 激活地形编…

LeetCode:6390. 滑动子数组的美丽值

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;6390. 滑动子数组的美丽值 题目描述&#xff1a;给你一个长度为 n 的整…

vulnhub DC:4渗透笔记

靶场下载地址:https://vulnhub.com/entry/dc416-2016,168/ 信息收集 使用nmap确定靶场ip地址 扫描ip确定开放端口 开放22 80端口&#xff0c;访问一下网页端(这边断了一次靶机ip改为192.168.100.138) 漏洞利用 登录框尝试爆破 发现用户名密码admin happy 登录进入后发现这里…

【自然语言处理】【大模型】LaMDA:用于对话应用程序的语言模型

LaMDA&#xff1a;用于对话应用程序的语言模型 《LaMDA: Language Models for Dialog Applications》 论文地址&#xff1a;https://arxiv.org/abs/2201.08239 相关博客 【自然语言处理】【大模型】LaMDA&#xff1a;用于对话应用程序的语言模型 【自然语言处理】【大模型】Dee…

如何衡量 SLO 的有效性?

衡量 SLO 及错误预算策略是否有效&#xff0c;其实就是看实际运行后&#xff0c;是否真的能达到我们的期望。我们可以从下面三个关键维度来看。 SLO 达成情况。我们用达成&#xff08;Met&#xff09;&#xff0c;或未达成&#xff08;Missed&#xff09;来表示。“人肉”投入…