sysadmin

HW5: Fuzzing

Due Date: 2024-03-17 23:59:59

Introduction

This is adapted from the AFLnet tutorial. And by adapted, I mean I’m making use of their tutorial.

Mac M1/2/3 users

OK, so what do you do if you don’t have access to an x86 machine? I’m assuming this is only relevant to the Apple M1/2/3 crowd, but I could be wrong. Turns out you can do this via Qemu emulation within UTM.

Steps to recreate:

  1. Download the Ubuntu 18.04 Server ISO.
  2. Create a new VM in UTM, selecting Emulation.
  3. Point this new VM at the Ubuntu ISO you downloaded previously.
  4. Within the VM settings, you’ll want to specify at least 2 cores, and at least 4GB of RAM. Please check the “Force multi-core” box.
  5. Boot the VM and install Ubuntu.
  6. Follow the AFLnet instructions as normal – don’t use Docker!

Using docker to simplify the process

If you are running into trouble getting this to run on your x86 machine, you can use this Dockerfile to build a working image:

# syntax=docker/dockerfile-upstream:master-labs
FROM ubuntu:18.04

RUN apt-get -y update && \
    apt-get -y install sudo \ 
    apt-utils \
    build-essential \
    openssl \
    clang \
    graphviz-dev \
    git \ 
    libcap-dev

# Download and compile AFLNet
ENV LLVM_CONFIG="llvm-config-6.0"


RUN git clone https://github.com/aflnet/aflnet.git /opt/aflnet && cd /opt/aflnet && make clean all && cd llvm_mode && make
#WORKDIR /opt/aflnet

# Set up environment variables for AFLNet
ENV AFLNET="/opt/aflnet"
ENV PATH="${PATH}:${AFLNET}"
ENV AFL_PATH="${AFLNET}"
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    AFL_SKIP_CPUFREQ=1
ENV WORKDIR="/home/testing"

RUN mkdir -p /home/testing/
RUN cd $WORKDIR && \
	git clone https://github.com/rgaufman/live555.git && \
	cd live555 && \
	git checkout ceeb4f4 && \
	patch -p1 < $AFLNET/tutorials/live555/ceeb4f4_states_decomposed.patch && \
	./genMakefiles linux && \
	make clean all

Then you can get ready to run the tests on Live555 with the following command:

❯ docker build --tag aflnet .
❯ docker run -it aflnet

$WORKDIR is set to /home/testing, so you can run the commands from the tutorial from there.

Running via docker on two different machines, I was able to get the following output:

aflnet run

Notice the different runtimes and total crashes found. Yay for stochastic processes!

Installation

Normally, you would use docker. These instructions are sticking around solely for the Mac M1/2/3 crowd. Skip to the Usage section if you’re using docker.

Prerequisites

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

AFLNet

Download AFLNet and compile it. We have tested AFLNet on Ubuntu 18.04 and Ubuntu 16.04 64-bit and it would also work on all environments that support the vanilla AFL and graphviz.

# First, clone this AFLNet repository to a folder named aflnet
❯ git clone <links to the repository> aflnet
# Then move to the source code foldercd 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 foldercd ../..
❯ export AFLNET=$(pwd)/aflnet
❯ export WORKDIR=$(pwd)

Setup PATH environment variables

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

Usage

AFLNet adds the following options to AFL. Run afl-fuzz --help to see all options. Please also see the FAQs section for common questions about these AFLNet’s options.

Example command:

❯ 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)>

Tutorial - Fuzzing Live555 media streaming server

Live555 Streaming Media is a C++ library for multimedia streaming. The library supports open protocols such as RTP/RTCP and RTSP for streaming. It is used internally by widely-used media players such as VLC and MPlayer and some security cameras & network video recorders (e.g., DLink D-View Cameras, Senstar Symphony, WISENET Video Recorder). In this example, we show how AFLNet can be used to fuzz Live555 and discover bugs in its RTSP server reference implementation (testOnDemandRTSPServer). Similar steps would be followed to fuzz servers implementing other protocols (e.g., FTP, SMTP, SSH).

If you want to run some experiments quickly, please take a look at ProFuzzBench. ProFuzzBench includes a suite of representative open-source network servers for popular protocols (e.g., TLS, SSH, SMTP, FTP, SIP), and tools to automate experimentation.

Step-0. Server and client compilation & setup

The newest source code of Live555 can be downloaded as a tarball at Live555 public page. There is also a mirror of the library on GitHub. In this example, we choose to fuzz an old version of Live555 which was commited to the repository on August 28th, 2018. While fuzzing this specific version of Live555, AFLNet exposed four vulnerabilites in Live555, two of which were zero-day. To compile and setup Live555, please use the following commands.

cd $WORKDIR
# Clone live555 repository
❯ git clone https://github.com/rgaufman/live555.git
# Move to the foldercd 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

As you can see from the commands, we apply a patch to make the server effectively fuzzable. In addition to the changes for generating a Makefile which uses afl-clang-fast++ to do the coverage feedback-enabled instrumentation, we make a small change to disable random session ID generation in Live555. In the unmodified version of Live555, it generates a session ID for each connection and the session ID should be included in subsequent requests sent from the connected client. Otherwise, the requests are quickly rejected by the server and this leads to undeterministic paths while fuzzing. Specifically, the same message sequence could exercise different server paths because the session ID is changing. We handle this specific issue by modifing Live555 in such a way that it always generates the same session ID.

Once Live555 source code has been successfully compiled, we should see the server under test (testOnDemandRTSPServer) and the sample RTSP client (testRTSPClient) placed inside the testProgs folder. We can test the server by running the following commands.

# Move to the folder keeping the RTSP server and clientcd $WORKDIR/live555/testProgs
# Copy sample media source files to the server foldercp $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

We should see the outputs from the sample client showing that it successfully connects to the server, sends requests and receives responses including streaming data from the server.

Step-1. Prepare message sequences as seed inputs

AFLNet takes message sequences as seed inputs so we first capture some sample usage scenarios between the sample client (testRTSPClient) and the server under test (SUT). The following steps show how we prepare a seed input for AFLNet based on a usage scenario in which the server streams an audio file in WAV format to the client upon requests. The same steps can be followed to prepare other seed inputs for other media source files (e.g., WebM, MP3).

We first start the server under test

cd $WORKDIR/live555/testProgs
❯ ./testOnDemandRTSPServer 8554

After that, we ask tcpdump data-network packet analyzer to capture all traffics through the port opened by the server, which is 8554 in this case. Note that you may need to change the network interface that works for your setup using the -i option.

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

Once both the server and tcpdump have been started, we run the sample client

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

When the client completes its execution, we stop tcpdump. All the requests and responses in the communication between the client and the server should be stored in the specified rtsp.pcap file. Now we use Wireshark network analyzer to extract only the requests and use the request sequence as a seed input for AFLNet. Please install Wireshark if you haven’t done so.

We first open the PCAP file with Wireshark.

❯ wireshark rtsp.pcap

This is a screenshot of Wireshark. It shows packets (requests and responses) in multiple rows, one row for one packet.

Analyzing the pcap file with Wireshark

To extract the request sequence, we first do a right-click and choose Follow->TCP Stream.

Follow TCP Stream

Wireshark will then display all requests and responses in plain text.

View requests and responses in plain text

As we are only interested in the requests for our purpose, we choose incoming traffic to the SUT-opened port by selecting an option from the bottom-left drop-down list. We choose 127.0.0.1:57998->127.0.0.1:8554 in this example which askes Wireshark to display all request messages sent to port 8554.

View requests in plain text

Finally, we switch the data mode so that we can see the request sequence in raw (i.e., binary) mode. Click “Save as” and save it to a file, say rtsp_requests_wav.raw.

View and save requests in raw binary

The newly saved file rtsp_requests_wav.raw can be fed to AFLNet as a seed input. You can follow the above steps to create other seed inputs for AFLNet, say rtsp_requests_mp3.raw and so on. We have prepared a ready-to-use seed corpus in the tutorials/live555/in-rtsp folder.

Step-2. Make modifications to the server code (optional)

Fuzzing network servers is challenging and in several cases, we may need to slightly modify the server under test to make it (effectively and efficiently) fuzzable. For example, this blog post shows several modifications to OpenSSH server to improve the fuzzing performance including disable encryption, disable MAC and so on. In this tutorial, the RTSP server uses the same response code 200 for all successful client requests, no matter what actual server state is. So to make fuzzing more effective, we can apply the simple patch in tutorials/live555/ceeb4f4_states_decomposed.patch that decomposes the big state 200 into smaller states. It makes the inferred state machine more fine grained and hence AFLNet has more information to guide the state space exploration.

Step-3. Fuzzing

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

Once AFLNet discovers a bug (e.g., a crash or a hang), a test case containing the message sequence that triggers the bug will be stored in replayable-crashes or replayable-hangs folder. In the fuzzing process, AFLNet State Machine Learning component keeps inferring the implmented state machine of the SUT and a .dot file (ipsm.dot) is updated accordingly so that the user can view that file (using a .dot viewer like xdot) to monitor the current progress of AFLNet in terms of protocol inferencing. Please read the AFLNet paper for more information.

Step-4. Reproducing the crashes found

AFLNet has an utility (aflnet-replay) which can replay message sequences stored in crash and hang-triggering files (in replayable-crashes and replayable-hangs folders). Each file is structured in such a way that aflnet-replay can extract messages based on their size. aflnet-replay takes three parameters which are 1) the path to the test case generated by AFLNet, 2) the network protocol under test, and 3) the server port number. The following commands reproduce a PoC for CVE-2019-7314.

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

To get more information about the discovered bug (e.g., crash call stack), you can run the buggy server with GDB or you can apply the Address Sanitizer-Enabled patch ($AFLNET/tutorials/live555/ceeb4f4_ASAN.patch) and recompile the server before running it.

What to turn in

Write up what you found and how you found it. Include screenshots and similar. You will also need to pick one of the other tutorials, and go through that exercise as well, writing it up as you go.

Everything should be in a markdown file in your repo called hw4/hw4.md. Commit and push this to your repo. Once you have done this, you can consider the assignment submitted.