Introspector report: link
A previous blog post by Project Zero
details a vulnerability exploited by NSO to hack iOS users in xpdf. This vulnerability is in the JBIG2Stream::readTextRegionSeg
function in xpdf.
xpdf is integrated into OSS-Fuzz, but the existing fuzzing did not cover JBIG2Stream::readTextRegionSeg
.
As shown in Figure 1, in the "Optimal target analysis" section of Fuzz Introspector report for xpdf, the
second function suggested is JBIG2Stream::reset()
.
The main function called by JBIG2Stream::reset()
is JBIG2Stream::readSegments
.
readSegments
actually calls the vulnerable function readTextRegionSeg
.
So the call tree for this fuzz target would be:
JBIG2Stream::reset()
readSegments()
readTextRegionSeg() // vulnerable function.
Figure 1: List of suggested targets for xpdf
Based on this suggestion, we wrote a new fuzzer to target JBIG2Stream::reset()
. As visible in the latest coverage reports, OSS-Fuzz is now exercising the vulnerable
function JBIG2stream::readTextRegionSeg()
.
This proves the usefulness of Fuzz Introspector in identifying and suggesting interesting new fuzz targets.
Introspector report: link
Fuzz Introspector provides a call-tree overview for each fuzz target (Figure 2). This overview shows the fuzz target coverage by color coding the call instructions. The red shaded areas are where the target fails to cover. As Figure 2 shows, jsonnet fuzz target fails to cover a big chunk of code.
Figure 2: Fuzz target coverage for jsonnet before adding new targets
Looking at the Fuzz blocker table (Figure 3), the top blocker is in the jsonnet_evaluate_snippet_aux()
funcion,
where a switch statement branches on an argument of type EvalKind.
Figure 3: Top fuzz blockers for jsonnet
Looking into the fuzz target call tree reveals that the argument of type EvalKind
is always set to a static value (REGULAR
in this case).
It means that the existing fuzz target has no way to explore other cases of the switch statement.
To improve the fuzzing coverage, one could quickly conclude that we need fuzz targets to
make a call to jsonnet_evaluate_snippet_aux()
with other possible values of Evalkind
. To this end we wrote two new fuzz targets to do
this via the provided interfaces
jsonnet_evaluate_snippet_multi()
and jsonnet_evaluate_snippet_stream()
.
This way we were able to unblock the jsonnet fuzzer and increase the call tree coverage dramatically (Figure 4).
Figure 4: Fuzz target coverage for jsonnet after adding new targets
Introspector report: link
MWDB uses file on malware samples, which is worrying to say the least.
After sending a
couple of
pull requests to tackle the low-hanging fruits,
the Remaining optimal interesting
functions
section showed that an awful lot of functions in the readelf.c
file weren't touched
at all by the fuzzers.
Looking at the Fuzz blockers,
file_tryelf
was likely the functions that should be called, and by checking out the
coverage of the relevant file,
the culprit was that file
needs to be passed data via a proper file descriptor
to exercise its elf-related codepath, and thus a file-based fuzzer was promptly added,
bumping the coverage close to 90%.
Introspector report: link
Bzip2's fuzz drivers hit 60% of the functions of the project by calling the compression and decompression functions with 2 fuzz drivers. The calltrees of bzip2_compress_target and bzip2_decompress_target do not show any significant fuzz blockers.
The file handling code is not being addressed, as seen in the Project functions overview and by the suggestions in the remaining optimal interesting functions.
Based on these hints, a single new file-based fuzzer was added to hit these recommended functions. The resulting fuzzer creates a temporary file, calls BZ2_bzdopen, then BZ2_bzwrite, followed by BZ2_bzread to read what was just written, then BZ2_bzclose, hitting all of the optimal interesting functions.
The addition of this fuzz driver increases the project's statically reachable coverage to 80%. This new report shows no recommended optimal interesting functions remain, however the Project Functions overview when sorted by functions not reached by fuzz drivers shows that a number of file handling functions are still being skipped.
Examining all of these missed functions show that two optimizations remain. Calling functions higher in the control flow graph will result in greater coverage. An example of this is substituting BZ2_bzReadOpen with BZ2_bzopen.
The other observation is that there are filename and FD versions of the file handling code. The fuzzer is split into two separate drivers to handle these 2 variations, with a few extra references to additional functions such as BZ2_bzReadGetUnused.
BZIP2 now has 100% of all functions statically reachable by the fuzz drivers.