Home
Unchained
Research Blog

FuzzSlice: Separating real CVEs from fakes through fuzzing

Aniruddhan Murali, Chainguard Labs Research Intern

TL;DR


A novel fuzzing technique, FuzzSlice, can help differentiate exploitable from false positive CVEs. Based on a set of 18 CVEs across OpenSSL, FuzzSlice found 12 of the CVEs to be exploitable and six to be false positives.


Introduction


In 2024, over 27,000 vulnerability reports, aka CVEs, have been filed so far. That’s over 100 CVEs per day: an overwhelming amount of CVEs for security teams to review and process manually. When new vulnerabilities are published upstream of Wolfi, the triage process is very manual and tedious for Chainguard engineers, but a vital part of minimizing risk throughout the software supply chain.


Now imagine a magic trick — one that lets you understand CVE within the context of your application with less manual triage. What if this trick could uncover vulnerable execution paths, provide crashing inputs for true positive CVEs, and weed out false positives, all automatically and in a timely fashion? 


Such a trick exists, and it’s called FuzzSlice. FuzzSlice is a cutting-edge fuzzer that provides detailed CVE insights through automatic test case generation. We ran FuzzSlice across 18 OpenSSL CVEs encountered by Chainguard’s security advisories to determine the tool’s effectiveness in reducing toil during triage.

We highlight key points from our findings below:


  • FuzzSlice identified that 12 out of 18 CVEs are exploitable. These CVEs were generally memory corruptions, which could lead to denial of service or arbitrary code execution.


  • FuzzSlice identified six CVEs that weren’t reachable (or could not be triggered) within the application context. 


Using FuzzSlice, we demonstrated that some CVEs can be exploited and that also some CVEs can be ignored. Regardless, Chainguard patches these CVEs, removing security concerns and lessening the burden on developers to triage false positives. In the remainder of this article, we provide an intro to fuzzing, a breakdown of the FuzzSlice project, and our evaluation of FuzzSlice across the sample of OpenSSL CVEs. 

 

Fuzzing 101: Who knew throwing random stuff at a program could be so productive?


Image showing workflow between Fuzzer and C/C++ Program.

At its core FuzzSlice is a fuzzer. The goal of all fuzzers is to automate the search for bugs in a program. This is accomplished by providing a massive amount of input in hopes to create strange behavior within the program. Such behavior could be evidence that a bug exists.


Consider a C/C++ project. We can think of testing this program automatically by passing a random input to the program and observing the execution path in the program. We can improve our random input by "mutating" it whenever it leads to an "interesting" or entirely new execution path. After millions of inputs covering different execution paths, this process may cause the program to crash, hang, or behave unpredictably — signs of hidden bugs that attackers could exploit as new CVEs. This approach to testing is known as fuzzing.


We visualize this process through a hypothetical project in the following call graph:

Image showing workflow and feedback loop from Fuzz to main.

In the above image, each node consists of a separate function in the project. An edge between two nodes represents a function calling another function (i.e., function B calls functions C and D). Assume a CVE exists in function B. The fuzzer passes random input to the entry method main, hoping to eventually trigger the CVE in function B.


A fuzzer that explores more code will inevitably uncover more bugs but it is often the case that covering 100% of the codebase is computationally infeasible. How can we ensure that the fuzzer reaches function B in a reasonable amount of time? This is the core question asked by the creators of FuzzSlice. Instead of fuzzing the entire codebase, FuzzSlice can focus on subsets of the call graph called slices.


FuzzSlice: Fuzz only slices of code!


FuzzSlice naturally extends the concept of reducing the code to fuzz by creating targeted code slices around key areas of interest, such as CVEs. This saves time and computing costs when ensuring certain regions of the call graph are covered.


We illustrate this idea of the slice on the same hypothetical project call graph described previously.

Image showing extended workflow and feedback loop from Fuzz to slice.

Assume the CVE exists in function B in the same way as before. Now, consider isolating a slice that includes function B along with all its dependencies — all the functions it calls, such as functions C and D. After compiling and linking these functions together (B, C, and D), we can focus on fuzzing this slice rather than the entire project. This allows the fuzzer to easily reach the CVE in function B and provide unique insights about the CVE.


Time to slice, dice, and fuzz!


To evaluate FuzzSlice, we selected 18 CVEs seen by Chainguard impacting OpenSSL. OpenSSL is a repository which is popular and commonly used as an upstream dependency by over 60 projects in the Wolfi distro


In total we found that 12/18 of these CVEs could be exploited. In contrast, the remaining six CVEs could not be exploited because they were not reachable within the context of the application. We provide an example of both exploitable and “bogus” CVEs below.


Case study 1: Heap overwrite — CVE-2022-3786


This CVE describes a memory corruption that exists within a routine that processes domain names The fuzzer can generate malicious domain names to trigger memory corruptions. Below, FuzzSlice crashes OpenSSL by passing the following malicious domain name (the string in the outlined box) within the code slice:


Screenshot of fuzz code.

FuzzSlice discovered that providing the domain name ghhhhhhhhhhhh.hhhhhh permits writing random bytes onto a server through OpenSSL, indicating CVE-2022-3786 poses a legitimate security risk.


Next, we highlight an existing bogus CVE that could be ignored within the context of Chainguard products. 


Case study 2: Null dereference — CVE-2022-3358


This CVE describes a NULL pointer dereference. FuzzSlice can execute the line (with a slice code coverage of 94%) but cannot trigger the NULL dereference. On further investigation, we find that application’s using SSL/TLS are not impacted by this issue, which is the case in the Chainguard container environment.


Discussion & conclusion


FuzzSlice helps identify exploitable CVEs from bogus CVEs. In addition, FuzzSlice optimizes compute resources and testing time by focusing on smaller code slices, making it a powerful tool for obtaining detailed information on CVEs. Using FuzzSlice, we are able to automate the process of separating exploitable CVEs from CVEs that can not be exploited. However, to remove security concerns, Chainguard continues to apply security patches — completely removing the burden of vulnerability triage.  


Currently, FuzzSlice only focuses on C/C++ projects, and we aim to expand to further languages in the future. Apart from that, FuzzSlice has the potential to enhance existing vulnerability reports or even expand into hunting zero-day vulnerabilities. If this is a project you’re interested in collaborating on, please contact us today!


Appendix


The docker for the FuzzSlice setup can be found by running:


docker pull ashamedbit/fuzzslice

Some tips on how to use the docker image (all paths are relative to default directory):


1. Set project name: Set the repository to fuzz within ./config.yaml within "test_library". The default project is OpenSSL.

2. Fuzz time budget: Set the time period for fuzzing - default 60 seconds.

3. Code target locations: You can set any code location to slice within: ./test_lib/openssl/targets.txt

4. Slice, dice and fuzz: run python3 main.py.

Share

Ready to Lock Down Your Supply Chain?

Talk to our customer obsessed, community-driven team.

Get Started