Fuzzm: 针对WebAssembly内存错误的模糊测试

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第1张

本文为看雪论坛优秀文章
看雪论坛作者ID:wx_秀玉轩晨


WebAssembly程序在JavaScript圈非常的火,可以大大加快浏览器的加载速度。但是WebAssembly的二进制程序通常由内存不安全的语言编译而成,例如C和C++,而且由于WebAssembly属于线性内存和缺乏保护的功能。

一些源码级别的内存漏洞可以在编译的WebAssembly二进制文件里边利用。而Fuzzm是第一个针对WebAssembly的模糊测试工具。

作者在github上开源了这款工具,本文详细介绍Fuzzm的配置流程。




背景介绍

  
看到了一篇对Web的WebAssembly程序的进行fuzzing的论文。

相信有许多的大佬已经十分熟悉模糊测试和WebAssembly了,这里还是简单介绍一下背景知识,这样会更有连贯性。




WebAssembly程序

  
webAssembly是一种新型的能够运行在现代web浏览器中运行的代码。这是一种低级的压缩的二进制格式的类汇编语言,能以近乎native的性能运行并且提供将c/c++、c#、Rust等高级语言编译为可以运行在web端的目标版本;它也被设计为允许与JavaScript一起运行。
  
WebAssembly已经被收录为W3C WebAssembly Community Group的开放标准,使用WebAssembly JavaScript API,你可以通过它们加载WebAssembly模块到一个Web App(node和JavaScript)中并且在两者间共享功能。
 
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第2张
   
需要注意的是WebAssembly并不是真正的汇编语言。所以不能像真正的汇编语言一样在真实的物理机上运行,总而言之,它是一个概念机上的机器语言。
  
正因如此,WebAssembly 指令有时候被称为虚拟指令。它比 JavaScript 代码更快更直接的转换成机器代码,但它们不直接和特定硬件的特定机器代码对应。
 
在浏览器下载WebAssembly后,使 WebAssembly 的迅速转换成目标机器的汇编代码。
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第3张
 
如图所示,如果想在页面上添加WebAssembly,需要将代码编译成.wasm文件。
 
使用WebAssembly,可以更快地在 web 应用上运行代码。这里有 几个 WebAssembly 代码运行速度比 JavaScript 高效的原因:

文件加载 - WebAssembly 文件体积更小,所以下载速度更快;

解析 - 解码 WebAssembly 比解析 JavaScript 要快;

编译和优化 - 编译和优化所需的时间较少,因为在将文件推送到服务器之前已经进行了更多优化,JavaScript 需要为动态类型多次编译代码;

重新优化 - WebAssembly 代码不需要重新优化,因为编译器有足够的信息可以在第一次运行时获得正确的代码;

执行 - 执行可以更快,WebAssembly 指令更接近机器码;

垃圾回收 - 目前 WebAssembly 不直接支持垃圾回收,垃圾回收都是手动控制的,所以比自动垃圾回收效率更高。





模糊测试AFL


模糊测试(fuzz testing, fuzzing)是一种软件测试技术。

其核心思想是將自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(assertion)失败,以发现可能的程序错误,比如内存泄漏。模糊测试常常用于检测软件或计算机系统的安全漏洞。
 
模糊测试诞生于1988年秋季的一个黑暗暴风雨之夜 [Takanen et al, 2008.]。巴顿·米勒教授坐在麦迪逊威斯康星州的公寓里,通过一条1200波特的电话线连接到他所属大学的计算机。

阵阵的雷暴在线路上造成噪音,这些噪音又导致两端的UNIX命令获得错误的输入,并导致崩溃。频繁的崩溃使他感到惊讶—我们编写的程序不是应该十分强大吗?作为一名科学家,他想探究该问题的严重程度及其原因。

因此,他为威斯康星大学麦迪逊分校的学生编写了一个编程练习,而该练习将使他的学生创建第一个模糊测试器。
 
这项作业的原文描述是这样的:

The goal of this project is to evaluate the robustness of various UNIX utility programs, given an unpredictable input stream. […] First, you will build a fuzz generator. This is a program that will output a random character stream. Second, you will take the fuzz generator and use it to attack as many UNIX utilities as possible, with the goal of trying to break them.
该项目的目标是在给定不可预测的输入流的情况下评估各种UNIX实用程序的健壮性。[…]首先,您将构建一个模糊发生器。这是一个将输出随机字符流的程序。其次,您将使用模糊发生器,并使用它来攻击尽可能多的UNIX实用程序,以试图破坏它们。

这个作业在不经意间抓住了模糊测试的本质:创建随机的输入,并持续性观察它是否会破坏目标应用程序,理论上只要运行足够长的时间,我们就会看到错误的发生。
 
AFL(american fuzzy lop)最初由Michał Zalewski开发,和libFuzzer等一样是基于覆盖引导(Coverage-guided)的模糊测试工具,它通过记录输入样本的代码覆盖率,从而调整输入样本以提高覆盖率,增加发现漏洞的概率。其工作流程大致如下:

1 从源码编译程序时进行插桩,以记录代码覆盖率(Code Coverage)

2 选择一些输入文件,作为初始测试集加入输入队列(queue)

3 将队列中的文件按一定的策略进行“突变”

4 如果经过变异文件更新了覆盖范围,则将其保留添加到队列中

5 上述过程会一直循环进行,期间触发了crash的文件会被记录下来

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第4张




Fuzzm


基于AFL模糊测试的原理,作者提出了首款针对WebAssembly的程序。测试原理如下图所示:

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第5张

首先,针对原始的.wasm二进制文(Original Binary)件,由于其为线性内存,, 我们可以在WebAssembly程序中添加Stack & Heap Canaries(堆栈检测点),用于检测WebAssembly程序是否发生内存溢出错误, wasm二进制程序也变成了Hardened Binary

根据之前AFL的知识,我们知道灰盒测试(Greybox Fuzzing)之所以有效是因为它依赖于程序执行期间的轻量级反馈来引导AFL的执行, 为了收集该反馈,AFL会进行编译插装来跟踪路径覆盖的的近似形式(approximate form of path coverage), 然后存储在跟踪位数组(trace bits array)中。

由于WebAssembly属于二进制程序,无法访问源码, 所以Fuzzm通过在所有的程序分支中插入代码来提取与AFL兼容的覆盖信息, 即instrument Approx Coverage。

最后Fuzzm对AFL进行了高度优化,因此可以在wasm虚拟机上对程序进行模糊测试。




开始运行


说了这么多前导知识,那么我们现在就开始Fuzzm的配置安装吧,首先我们从github网站上把这个项目拉下来。https://github.com/fuzzm/fuzzm-project

由于要从外网下载各种配置资源,所以这里建议大家kexueshangwang。


5.1 安装各种环境


  1. 下载 Rust 和 cargo

curl https://sh.rustup.rs -sSf | sh

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第6张

默认选1即可:

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第7张

下载完成后,输入以下命令:
source $HOME/.cargo/env
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第8张

下载 wasmtime:
curl https://wasmtime.dev/install.sh -sSf | bash
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第9张

构建 wasmtime:
git clone --recurse-submodules /    https://github.com/bytecodealliance/wasmtime.git
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第10张
 
之后开始构建wasmtime:
cd wasmtimecargo build --release
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第11张
 
经过漫长的等待后构建完成,当然,,网速快的除外。:
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第12张
 
将程序连接到全局:
sudo ln -s /home/mzs/Desktop/fuzzm-project/wasmtime/target/release/wasmtime /usr/bin/wasmtime

从Ubuntu软件源安装Node.js 和 npm
sudo apt updatesudo apt install nodejs npm
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第13张
 
配置完成,输入nodejs --version 和 npm --version查看版本:
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第14张

下载 wasi sdk:
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-11/wasi-sdk-11.0-linux.tar.gztar xvf wasi-sdk-11.0-linux.tar.gz

在fuzzm-project目录下 执行npm install。

5.2 开始配置


进入 AFL-wasm文件夹:
make & make install

配置完成后, 使用afl-fuzz发现有以下错误:
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第15张

这是因为系统没有找到对应的库文件. 我们使用以下命令链接即可:
sudo ln /path/to/fuzzm-project/AFL-wasm/wasmtime-v0.20.0-x86_64-linux-c-api/lib/libwasmtime.so /usr/lib/libwasmtime.so

注意,下载路径要配套, 库文件的地址是你下载项目的位置。
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第16张
然后我们在运行afl-fuzz,情况已经正常:
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第17张

进入wasm_instrumenter文件夹:

cargo build --release

这个文件夹可以对wasm进行insert canaries 和 instrument coverage操作, 耐心等上一段时间, 配置完成后:
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第18张
 
开始链接到全局:
sudo ln -s /home/mzs/Desktop/fuzzm-project/wasm_instrumenter/target/release/afl_branch /usr/bin/afl_branch sudo ln -s /home/mzs/Desktop/fuzzm-project/wasm_instrumenter/target/release/canaries /usr/bin/canaries



5.3 开始fuzz

 
a. 进入 motivating-example 文件夹

我们可以看到这里有一段实例代码:
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第19张
 
我们先对现成的wasm程序进行模糊测试。
chmod +x vuln-cov-canaries.wasm WASM_MODE=1 afl-fuzz -i testcases/ -o output_cov_canaries ./vuln-cov-canaries.wasm
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第20张

b. 编译项目,进入 benchmarks/openjpeg文件夹:
./wasm-compile-and-instrument.shcd bin/WASM_MODE=1 afl-fuzz -i ../tests/ -o output_canaries ./opj_compress.instr.wasm
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第21张
 
c. 将c文件转化为wasm,并进行fuzz。

我们以vuln.c 文件为例,首先我们从motivating-example文件夹中,,拷贝testcases 和 vuln.c,然后输入以下命令::
../wasi-sdk-11.0/bin/clang --sysroot=../wasi-sdk-11.0/share/wasi-sysroot -O2 -D USE_JPIP=1 vuln.c -o vuln.wasm

将c文件转化为wasm文件。
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第22张
之后进行insert canaries 和 instrument coverage操作, 注意生成文件后使用chmod +x xxx.wasm授权。
afl_branch vuln.wasm vuln.instr.wasm canaries vuln.instr.wasm vuln-cov-canaries.wasm
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第23张
 
然后开始fuzzing:
WASM_MODE=1 afl-fuzz -i testcases/ -o outputs ./vuln-cov-canaries.wasm

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第24张
 
如何将项目转化为wasm?

这里我们以benchmarks/openjpeg为例。进入文件夹,,打开wasm-compile.sh文件。
Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第25张
可以看到:想要转化为wasm文件,需要将所有的依赖文件转化过去。
 

参考链接:
 
WebAssembly参考:
https://cache.one/read/7565547
https://www.smashingmagazine.com/2017/05/abridged-cartoon-introduction-webassembly/

AFL参考:
https://myfzy.top/2021/03/16/symcc+afl/

Fuzzm项目地址:
https://github.com/fuzzm/fuzzm-project

论文参考:
Fuzzm: Finding Memory Bugs through Binary-Only Instrumentation and Fuzzing of WebAssembly
https://arxiv.org/pdf/2110.15433.pdf



Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第26张


看雪ID:wx_秀玉轩晨

https://bbs.pediy.com/user-home-932916.htm

*本文由看雪论坛 wx_秀玉轩晨 原创,转载请注明来自看雪社区

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第27张

# 往期推荐

1.0rays战队2021圣诞校内招新赛题解

2.2022腾讯游戏安全初赛一题解析

3.一文读懂PE文件签名并手工验证签名有效性

4.一款路由器安全测试

5.一道pwn题目2e4zu的深入分析

6.CNVD-2018-01084 漏洞复现报告(service.cgi 远程命令执行漏洞)



Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第28张



Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第29张

球分享

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第30张

球点赞

Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第31张

球在看



Fuzzm: 针对WebAssembly内存错误的模糊测试 网络安全 第32张

点击“阅读原文”,了解更多!

参与评论