• Author:ZERO-A-ONE
  • Date:2021-06-11

​ AFLNet 是一个用于协议实现的灰盒模糊器。与现有的协议模糊器不同,它采用突变方法,除了代码覆盖率反馈外,还使用状态反馈来指导模糊测试过程。AFLNet 以服务器和实际客户端之间记录的消息交换语料库为种子。不需要协议规范或消息语法。它充当客户端并重播发送到服务器的原始消息序列的变化,并保留那些有效增加代码或状态空间覆盖率的变化。为了识别由消息序列执行的服务器状态,AFLNet 使用服务器的响应代码。根据这个反馈,AFLNet 识别状态空间中的渐进区域,并系统地转向这些区域

一、安装AFLNAT

1.1 安装环境

# Install clang (as required by AFL/AFLNet to enable llvm_mode)
$ sudo apt-get install clang
# Install graphviz development
$ sudo apt-get install graphviz-dev
$ sudo apt install llvm

1.2 AFLNet

​ 我们已经在Ubuntu 18.04和Ubuntu 16.04 64位上测试了AFLNet,它也可以在所有支持普通AFL和graphviz的环境下工作

# First, clone this AFLNet repository to a folder named aflnet
git clone <links to the repository> aflnet
# Then move to the source code folder
cd aflnet
make clean all
cd llvm_mode
# The following make command may not work if llvm-config cannot be found
# To fix this issue, just set the LLVM_CONFIG env. variable to the specific llvm-config version on your machine
# On Ubuntu 18.04, it could be llvm-config-6.0 if you have installed clang using apt-get
make
# Move to AFLNet's parent folder
cd ../..
export AFLNET=$(pwd)/aflnet
export WORKDIR=$(pwd)

1.3 设置PATH环境变量

export PATH=$AFLNET:$PATH
export AFL_PATH=$AFLNET

二、用法

​ AFLNet 为 AFL 添加了以下选项。运行afl-fuzz --help以查看所有选项。有关这些 AFLNet 选项的常见问题,另请参阅常见问题部分

  • -N netinfo服务器信息(例如,tcp://127.0.0.1/8554)
  • -P protocol:待测试的应用协议(例如,RTSP、FTP、DTLS12、DNS、DICOM、SMTP、SSH、TLS、DAAP-HTTP、SIP)
  • -D usec:(可选)服务器完成初始化的等待时间(以微秒为单位)
  • -K:(可选)在使用完所有请求消息后发送 SIGTERM 信号以优雅地终止服务器
  • -E:(可选)启用状态感知模式
  • -R:(可选)启用区域级变异算子
  • -F:(可选)启用假阴性减少模式
  • -c script :(可选)服务器清理脚本的名称或完整路径
  • -q algo:(可选)状态选择算法(例如,1. RANDOM_SELECTION, 2. ROUND_ROBIN, 3. FAVOR)
  • -s algo:(可选)种子选择算法(例如,1. RANDOM_SELECTION, 2. ROUND_ROBIN, 3. FAVOR)

示例命令:

afl-fuzz -d -i in -o out -N <server info> -x <dictionary file> -P <protocol> -D 10000 -q 3 -s 3 -E -K -R <executable binary and its arguments (e.g., port number)>

三、教程 - Fuzzing Live555 流媒体服务器

Live555 Streaming Media是一个用于多媒体流媒体的 C++ 库。该库支持开放协议,例如用于流式传输的 RTP/RTCP 和 RTSP。它被广泛使用的媒体播放器如VLCMPlayer以及一些安全摄像机和网络视频录像机(例如,DLink D-View 摄像机、[Senstar Symphony](http://cdn.aimetis.com/public/Library/Senstar Symphony User Guide en-US.pdf)、WISENET Video Recorder)在内部使用。在此示例中,我们展示了如何使用 AFLNet 对 Live555 进行模糊测试并发现其 RTSP 服务器参考实现 (testOnDemandRTSPServer) 中的错误。将遵循类似的步骤对实现其他协议(例如,FTP、SMTP、SSH)的服务器进行模糊测试

​ 如果您想快速运行一些实验,请查看ProFuzzBench。ProFuzzBench 包括一套用于流行协议(例如,TLS、SSH、SMTP、FTP、SIP)的代表性开源网络服务器,以及自动化实验的工具

3.1 服务器和客户端的编译与配置

​ Live555 的最新源代码可以在Live555公共页面下载下来是一个tar压缩文件。GitHub 上也该库的镜像。在这个例子中,我们选择对2018 年 8 月 28 日提交到存储库的旧版本Live555 进行模糊测试。 在对这个特定版本的 Live555 进行模糊测试时,AFLNet 暴露了 Live555 中的四个漏洞,其中两个是0 Day漏洞。要编译和设置 Live555,请使用以下命令

cd $WORKDIR
# Clone live555 repository
git clone https://github.com/rgaufman/live555.git
# Move to the folder
cd live555
# Checkout the buggy version of Live555
git checkout ceeb4f4
# Apply a patch. See the detailed explanation for the patch below
patch -p1 < $AFLNET/tutorials/live555/ceeb4f4.patch
# Generate Makefile
./genMakefiles linux
# Compile the source
make clean all

​ 正如您从命令中可以看到的,我们应用了一个补丁来使服务器有效地可模糊化。除了生成一个使用afl-clang-fast++来实现覆盖反馈功能的Makefile的更改之外,我们还做了一个小更改来禁用Live555中的随机会话ID生成。在未修改的Live555版本中,它为每个连接生成一个会话ID,该会话ID应该包括在从已连接的客户机发送的后续请求中。否则,请求将很快被服务器拒绝,这将导致在fuzzing时产生不确定的路径。具体来说,相同的消息序列可以运行不同的服务器路径,因为会话ID正在更改。我们通过修改Live555以使它总是生成相同的会话ID来处理这个特定的问题

​ 一旦Live555源代码被成功编译,我们应该看到被测试的服务器(testOnDemandRTSPServer)和示例RTSP客户机(testRTSPClient)被放置在testProgs文件夹中。我们可以通过运行以下命令来测试服务器

# Move to the folder keeping the RTSP server and client
cd $WORKDIR/live555/testProgs
# Copy sample media source files to the server folder
cp $AFLNET/tutorials/live555/sample_media_sources/*.* ./
# Run the RTSP server on port 8554
./testOnDemandRTSPServer 8554
# Run the sample client on another screen/terminal
./testRTSPClient rtsp://127.0.0.1:8554/wavAudioTest

​ 我们应该看到示例客户机的输出显示它成功连接到服务器,发送请求并接收来自服务器的响应(包括流数据)

3.2 准备消息序列作为种子输入

​ AFLNet 将消息序列作为种子输入,因此我们首先捕获示例客户端 (testRTSPClient) 和被测服务器 (SUT) 之间的一些示例使用场景。下面的步骤展示了我们如何根据一个使用场景为AFLNet准备一个种子输入,在这个场景中,服务器根据请求将一个WAV格式的音频文件流到客户端。同样的步骤也可以用于为其他媒体源文件(例如WebM、MP3)准备其他种子输入

​ 我们首先启动被测服务器

cd  $WORKDIR /live555/testProgs
./testOnDemandRTSPServer 8554

​ 之后,我们要求tcpdump数据网络数据包分析器捕获通过服务器开放的端口(在本例中为8554)的所有流量。注意,您可能需要使用-i选项更改为您的设置工作的网络接口

sudo tcpdump -w rtsp.pcap -i lo port 8554

​ 一旦服务器和tcpdump都启动,我们就运行示例客户机

cd $WORKDIR/live555/testProgs
./testRTSPClient rtsp://127.0.0.1:8554/wavAudioTest

​ 当客户端完成它的任务时,我们停止 tcpdump。客户端和服务器之间通信中的所有请求和响应都应该存储在指定的 rtsp.pcap 文件中。

​ 在我们使用Wireshark 网络分析器仅提取请求并将请求序列用作 AFLNet 的种子输入。如果您还没有安装 Wireshark,请安装

​ 我们首先用 Wireshark 打开 PCAP 文件

wireshark rtsp.pcap

​ 这是Wireshark的截图。它以多行显示数据包(请求和响应),一行显示一个数据包
在这里插入图片描述

​ 要提取请求序列,我们首先右键单击并选择Follow->TCP Stream
在这里插入图片描述

​ Wireshark将以纯文本形式显示所有请求和响应
在这里插入图片描述

由于我们只对用于我们目的的请求感兴趣,因此我们通过从左下角的下拉列表中选择一个选项来选择进入 SUT 打开的端口的流量。本例中我们选择127.0.0.1:57998->127.0.0.1:8554,它要求Wireshark显示发送到端口8554的所有请求消息
在这里插入图片描述

​ 最后,我们切换数据模式,以便以原始(即二进制)模式查看请求序列。点击“另存为”并将其保存到一个文件中,例如rtsp_requests_wave .raw
在这里插入图片描述

​ 新保存的文件rtsp_requests_wav.raw可以作为种子输入输入到AFLNet。您可以按照上面的步骤为AFLNet创建其他种子输入,比如rtsp_requests_mp3.raw等等。我们在tutorials/live555/in-rtsp文件夹中准备了一个即用型的种子语料库

3.3 修改服务器代码(可选)

​ 模糊网络服务器是具有挑战性的,在一些情况下,我们可能需要稍微修改测试中的服务器,使其(有效和高效)可以进行模糊测试。例如,这篇博文展示了对OpenSSH服务器的一些修改,以提高模糊性能,包括禁用加密、禁用MAC等。在本教程中,RTSP服务器对所有成功的客户机请求都使用相同的响应代码200,而不管服务器的实际状态是什么。因此,为了使模糊更有效,我们可以使用这个简单的补丁将大的200个状态分解成小的状态。它使推断的状态机粒度更细,因此AFLNet有更多的信息来指导状态空间的探索

3.4 模糊测试

$ cd $WORKDIR/live555/testProgs
$ afl-fuzz -d -i $AFLNET/tutorials/live555/in-rtsp -o out-live555 -N tcp://127.0.0.1/8554 -x $AFLNET/tutorials/live555/rtsp.dict -P RTSP -D 10000 -q 3 -s 3 -E -K -R ./testOnDemandRTSPServer 8554

​ 一旦AFLNet发现一个bug(例如,崩溃或挂起),包含触发错误的消息序列的测试用例将存储replayable-crashesreplayable-hangs文件夹中。在模糊测试过程中,AFLNet 状态机学习组件不断推断 SUT 的已实现状态机,并相应地更新 .dot 文件 (ipsm.dot),以便用户可以查看该文件(使用类似 xdot 的 .dot 查看器)以监控 AFLNet 在协议推理方面的当前进展。请阅读 AFLNet 论文以获取更多信息

3.5 复现发现的崩溃

​ AFLNet有一个实用程序(AFLNet -replay),可以重放存储在崩溃和挂起触发文件中的消息序列(在消息序列replayable-crashesreplayable-hangs文件夹)。每个文件的结构使得 aflnet-replay 可以根据消息的大小提取消息。aflnet-replay 需要三个参数,它们是 1) AFLNet 生成的测试用例的路径,2) 被测网络协议,以及 3) 服务器端口号。以下命令复制了CVE-2019-7314的 PoC

cd $WORKDIR/live555/testProgs
# Start the server
./testOnDemandRTSPServer 8554
# Run aflnet-replay
aflnet-replay $AFLNET/tutorials/live555/CVE_2019_7314.poc RTSP 8554

​ 要获得有关发现的错误(例如崩溃调用堆栈)的更多信息,您可以使用GDB运行有问题的服务器,或者您可以应用启用地址清理器的补丁 ($AFLNET/tutorials/live555/ceeb4f4_ASAN.patch) 并重新编译服务器在运行它之前

四、常见问题

4.1 如何扩展 AFLNet?

AFLNet采用模块化设计,易于扩展

4.1.1 如何添加对其他协议的支持?

如果您想支持其他协议,您只需要按照以下步骤操作即可

步骤1:实现2个函数来解析请求和响应序列

您可以使用extract_requests_*extract_response_codes_*函数作为参考。这些函数应该分别在aflnet.haflnet.c 中声明和实现。请注意,请使用相同的函数参数

步骤2:更新main函数以支持新的协议

请更新处理-P主函数中选项的代码以支持新协议

4.1.2 我如何实现另一个搜索策略?

这很简单。您只需要更新两个函数choose_target_statechoose_seed。该功能update_scores_and_select_next_state也可能需要扩展

4.2 如果我没有通过添加-E选项来启用状态感知模式,会发生什么?

如果-E不启用,即使 AFLNet 仍然管理请求的边界信息,因此它仍然可以遵循协议的序列图——发送请求,等待响应等,这是正常联网的 AFL 不支持的. 但是,在此设置中,AFLNet 将忽略响应,并且不会根据响应代码构建状态机。因此,AFLNet 无法使用状态机来指导探索

4.3 当我需要 -c 选项时,我应该在清理脚本中写什么?

您可能需要提供此选项以使网络模糊测试更具确定性。例如,当您对 FTP 服务器进行模糊测试时,您需要清除共享文件夹中先前模糊测试迭代中创建的所有文件/文件夹,因为如果不这样做,服务器将无法创建文件(如果存在)。这意味着 FTP 服务器在收到来自客户端的相同请求序列时会以不同的方式工作,在这个模糊测试设置中是 AFLNet。所以基本上脚本应该包括清理影响服务器行为的环境的命令,并为服务器提供一个干净的启动环境

4.4 什么是假阴性减少模式,我应该何时使用 -F 启用它?

与无状态程序(例如,像 LibPNG 这样的图像处理库)不同,几个有状态服务器(例如,上面教程中的 RTSP 服务器)在消耗了来自客户端的所有请求后不会自行终止,在这个模糊测试设置中是 AFLNet。因此 AFLNet 需要通过发送 SIGTERM 信号(指定 -K 时)来优雅地终止服务器。否则,AFLNet 会将正常的服务器执行检测为挂起。然而,问题是如果 AFLNet 过早地发送 SIGTERM 信号,比如在所有请求消息都发送到服务器之后,服务器可能会在它仍在执行一些可能导致服务器崩溃的任务时被迫终止(即,漏报——服务器崩溃被遗漏)。假阴性减少模式旨在处理此类情况。然而,它可能会降低fuzzing效率,从而导致较慢的执行速度

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐