一、fuzz
模糊测试 (fuzz testing, fuzzing)是一种软件测试技术。其核心思想是自动或半自动的生成随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(assertion)失败,以发现可能的程序错误,比如内存泄漏。模糊测试常常用于检测软件或计算机系统的安全漏洞。
进行软件漏洞挖掘时,通常有静态分析(staticanalysis)、动态分析(dynamicanalysis)、符号执行(symbolicexecution)、模糊测试(fuzzing)这几种技术手段。
静态分析就是不真正的运行目标程序,但是通过对它进行各种语法、语义、数据流等的分析,来进行漏洞发掘。静态分析是由静态分析软件完成的;它的速度快,但是误报率高。
动态分析就是我们通常见到的大佬们用od一步步跟踪程序运行进行的分析。它的准确率很高,但是需要调试人员丰富的知识储备,而且这种调试方法很难进行大规模的程序漏洞挖掘。
符号执行简单来说,就是试图找到什么输入对应什么样的运行状态,它要去覆盖所有的执行路径。因此,当被分析的程序比较复杂,有很多执行路径时,就会遇到路径爆炸的问题。
模糊测试不需要人过多的参与,也不像动态分析那样要求分析人员有丰富的知识。简单解释,它就是用大量的输入数据自动去执行程序,从而发现哪些输入能够使程序发生异常,进而分析可能存在的漏洞。当前比较成功的fuzzer(执行模糊测试的程序)有AFL、libFuzzer、OSS-Fuzz等。
二、syzkaller简介
syzkaller是google的安全研究人员开发并维护的内核fuzz工具。它主要是用go写的,也有少部分C代码,支持akaros/fuchsia/linux/android/freebsd/netbsd/openbsd/windows等系统,发现的漏洞多达上千。不过它支持最全面的还是linux系统,对其它系统的支持都不同程度差一点,也不支持Darwin/XNU。有研究人员做过移植syzkaller fuzz windows WSL和Darwin/XNU的尝试,也都取得了较好的成果。可以说,syzkaller是当今宇宙最强大的内核fuzz工具了。
三、syzkaller整体架构
syz-manager通过ssh调用syz-fuzzer,syz-fuzzer和syz-manager之间通过RPC进行通信。syz-fuzzer将输入传给syz-executor,从kernel中读取代码覆盖率信息。syz-executor执行syscall系统调用。
我们再看一下代码的整体目录。
- dashboard目录:主要与syzbot有关,syzbot会自动fuzz linux内核主线分支并向内核邮件列表报告发现的错误。我们可以在https://syzkaller.appspot.com上看到相关的情况。
-
docs目录:相关文档。
-
pkg目录:配置文件。
-
prog目录:目标系统相关信息以及需要执行的系统调用。
-
sys目录:系统调用描述。该目录下的结构如下图。
四、使用syzkaller进行Linux内核漏洞挖掘
环境准备
- 准备一台linux机器
安装基本软件
sudo apt-get install debootstrap
sudo apt install qemu-kvm
sudo apt-get install subversion
sudo apt-get install git
sudo apt-get install make
sudo apt-get install qemu
sudo apt install libssl-dev libelf-dev
sudo apt-get install flex bison libc6-dev libc6-dev-i386 linux-libc-dev linux-libc-dev:i386 libgmp3-dev libmpfr-dev libmpc-dev
apt-get install g++
apt-get install build-essential
apt install golang-go
apt install gcc
- 获取syzkaller源码
git clone https://github.com/google/syzkaller.git
- 获取linux内核代码,可在linux kernel官网下载
- 生成小型Linux发行版所需的镜像(用debootstrap生成)
这里使用官方提供的构建脚本。实际上我们可以参考脚本内容构建其他发行版的镜像。
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh
./create-image.sh
完成后可以看到出现了:stretch.id_rsa、stretch.id_rsa.pub、stretch.img 这几个文件。
构建
- 编译syzkaller
root@kylinos:~/fuzz-kernel/syzkaller# cd ~/fuzz-kernel/syzkaller/
root@kylinos:~/fuzz-kernel/syzkaller# make
- 编译kernel
1、在内核源码目录同级创建目录build
2、拷贝需要测试系统的内核config到build目录下并改名.config
3、配置编译内核选项
make O=../build/ menuconfig
4、增加syzkaller测试所需要配置(通过3步的menuconfig进行查找配置,并修改配置。y代表编译到核内)
CONFIG_KCOV=y
CONFIG_DEBUG_INFO=y
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
5、编译
make O=../build/ -j10
6、在内核源码目录同级创建目录install_path/boot目录
7、安装内核到…/install_path
export INSTALL_PATH=../install_path/boot && export INSTALL_MOD_PATH=../install_path/ && export INSTALL_MOD_STRIP=1 && make modules_install install O=../build
- 添加内核核外模块到镜像。
root@kylinos:~/fuzz-kernel# ls
kernel my.cfg stretch syzkaller syzkaller.sh vm.log
root@kylinos:~/fuzz-kernel# mount stretch/stretch.img /mnt/
mount: /mnt/: /root/fuzz-kernel/stretch/stretch.img 已经挂载.
root@kylinos:~/fuzz-kernel# cp kernel/install_path/lib/modules/5.4.18-32+ /mnt/lib/modules/ -rfa
root@kylinos:~/fuzz-kernel# chroot /mnt/
root@kylinos:/# depmod -a -b . 5.4.18-32+
root@kylinos:/# exit
exit
root@kylinos:~/fuzz-kernel# umount /mnt
运行syzkaller
- 测试构建镜像是否正常。(使用以下qemu启动命令测试,正常无任何报错进入系统,然后init 0 关机。)
root@kylinos:~/fuzz-kernel# vim syzkaller.sh
qemu-system-x86_64 \
-kernel /root/fuzz-kernel/kernel/build/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda debug earlyprintk=serial slub_debug=QUZ" \
-hda /root/fuzz-kernel/stretch/stretch.img \
-net user,hostfwd=tcp::10021-:22 -net nic \
-enable-kvm \
-nographic \
-m 2G \
-smp 2 \
-pidfile vm.pid \
2>&1 | tee vm.log
- 运行syzkaller
编写配置文件
root@kylinos:~/fuzz-kernel# vim ./syzkaller/my.cfg
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "/root/fuzz-kernel/syzkaller/workdir", #工作目录
"kernel_obj": "/root/fuzz-kernel/kernel/build", #内核编译build目录
"image": "/root/fuzz-kernel/stretch/stretch.img", #镜像位置
"sshkey": "/root/fuzz-kernel/stretch/stretch.id_rsa",
"syzkaller": "/root/fuzz-kernel/syzkaller",
"procs": 8,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "/root/fuzz-kernel/kernel/build/arch/x86/boot/bzImage",
"cpu": 2,
"mem": 2048
}
}
配置无误后运行syzkaller
root@kylinos:~/fuzz-kernel/syzkaller# ./bin/syz-manager -config=my.cfg
启动成功如图示: