0x01 什么是oss-fuzz
谷歌的oss-fuzz能够针对开源软件进行持续的模糊测试,其测试开发团队也提到“OSS-Fuzz的目的是利用更新的模糊测试技术与可拓展的分布式执行相结合,提高一般软件基础架构的安全性与稳定性。OSS-Fuzz结合了多种模糊测试技术/漏洞捕捉技术(即原来的libfuzzer)与清洗技术(即原来的AddressSanitizer),并且通过ClusterFuzz为大规模可分布式执行提供了测试环境。”,当然fuzzer也可以选择AFL,libfuzzer
先下载源码
0x02 三个主要的文件
project.yaml
homepage:You project’s homepage.(没啥用)
laguange:项目编写的编程语言,一般是c或c++
primary_contact, auto_css:联系人(也没啥用)
sanitizer: 可以使用去更有效的查找 memory address bugs
architectures: 架构
其它没啥用的就不一一介绍了
写个例子:
1 | homepage: "https://www.baidu.com" |
Dockerfile
这个很重要,为项目定义了docker 镜像,build.sh也将在镜像中运行,长这样
1 | FROM gcr.io/oss-fuzz-base/base-builder # base image with clang toolchain,这个是谷歌上的镜像,把可先把它拖到dockerhub上然后替换掉,也可以换成我已经拖好的,后面会给出 |
build.sh
构建脚本,用来编译项目的,生成的二进制文件应放在$OUT
中
示例,一般就是编译和复制语句
1 | #!/bin/bash -eu |
以下位置对应的环境变量
/out/
–> $OUT
:用来存储构建好的文件
/src/
–> $SRC
: 放源文件的位置
/work/
–> $WORK
: 存储中间文件的位置
更多的变量可以参考官方文档
0x3 拉取镜像
oss中用到的镜像都需要从谷歌拉取,有两种解决方法,给docker挂个代理然后直接pull;或者利用github+dockerhub的方法将所有的镜像先拖到dockerhub上,然后将源码中所有的gcr.io/oss-fuzz-base/xxxx
改成对应dockerhub上的就行。教程(如果你壕无人性可以直接买个国外服务器,就不会有这些烦恼了)
也可以用我拉好的:
1 | gcr.io/oss-fuzz-base/base-image --> r4bbit/base-image |
0x4 起oss中自带的project
我们可以看到在project中有很多项目,这些都已经写好了build.sh、Dockerfile等必要文件
举个例子:openssl
1 | # ls projects/openssl/ |
build.sh文件不用修改,需要将Dockerfile文件中的FROM gcr.io/oss-fuzz-base/base-builder
修改为FROM r4bbit/oss-fuzz:latest
并且,infra/help.py 中BASE_IMAGES
修改为对应的镜像地址
之后 根据文档中的test locally
步骤将fuzz起起来
举个例子,我这里用的是engine 选 afl,sanitizer 选undefined
1 | # python infra/helper.py build_image openssl |
build_fuzzers
后可以在/path/to/oss/build/out中看到多了一个openssl文件夹,openssl而里面就有编译好的二进制文件
1 | # python infra/helper.py check_build openssl --sanitizer undefined --engine afl |
check build pass后就可以开始fuzz了,(其实个觉得好像也没必要check,貌似也只是跑了一句docker),会在build/out/openssl下面生成新的文件夹server_afl_undefined_out
,里面的东西就跟AFL一样了
0x5 fuzz自己写的程序
如果想fuzz自己的程序就需要写build.sh和Dockerfile了,project.yaml倒不是很重要,模板上面已经有了,这里我直接举自己的例子。
先用c写一个漏洞程序 test.c
1 |
|
然后上传到github或者gitee,接下来写Dockerfile,直接套就行了
1 | FROM r4bbit/oss-fuzz:latest |
build.sh,这里说一下我踩过的坑
1 | # build project |
用gcc进行编译(肯定是我脑子糊了),在run_fuzzer时会报错:原因是没有插桩
1 | [-] Looks like the target binary is not instrumented! The fuzzer depends on |
所以需要换afl-gcc
进行编译,在build_fuzzers步骤已经将afl-gcc
等文件复制到/out/
目录下了,所以将编译命令改成$OUT/afl-gcc /src/test/test.c -o /src/test/test
,成功调用了afl-gcc进行编译,但是开始fuzz时又发现,还是没有插桩
对比一下正常情况下afl-gcc的编译情况可以发现
build.sh中没有调用afl-as,而afl-as的作用就是插桩,正常来讲指定AFL_PATH
就能解决了,然而这里并没有解决,最后结合AFL源码,我用了一个方法:在build中建立 afl-as 软链接到 as
1 | afl-gcc.c 中 find_as,让它在这里自己找到as_path |
问题解决,最后成功的build.sh脚本
1 | #!/bin/bash -eu |