What is fuzzing?
Modern fuzzing solutions analyze the structure of the code they are testing and generate thousands of automated test cases per second. The process is designed to reach as many new program states as possible with the generated inputs . In addition, the fuzzer also marks the individual paths followed by these inputs and thus receives detailed feedback on the test coverage achieved when executing the source code. In this way, fuzzers learn more about the structure of the expected input with each iteration.
Type Of Fuzzing
1- Dumb Fuzzer
2- Generation Fuzzer
3- Coverage Guided Fuzzer
What is Dumb Fuzzer
?
Dumb fuzzer works without having any knowledge about the data attempts to random input
, also no understanding of file format/network protocol is required. also can take lot of time (depending up on your luck).
Ex Radmasa
What is Generation Fuzzer
?
In contrast to Dumb Fuzzers, here an understanding of the file format / protocol is very important. Itโs about โgeneratingโ the inputs from the scratch based on the specification/format.
What is Coverage Guided Fuzzer
?
Coverage guided fuzzing
uses program instrumentation to trace the code coverage and monitors program flow by using instrumentation. no knowledge of the file format is required and It modifies the file using its own algorithms and check for new code path coverage/crash.
Ex ( AFL, WinAFL, HonggFuzz, LibFuzzer, Jazzer )
What is Jazzer
?
Today, we will dive into the Java world and check out the most popular Java fuzzing solution, Jazzer is used to automatically generate malicious inputs for Java programs.
Tools setup :
We will now go through the process of installing Jazzer so you can easily follow along on my VM machine (Ubuntu 20.04).
Jazzer has the following dependencies when being built from source:
1- Install Bazel 4 or later
2- Install JDK 8 or later (e.g. OpenJDK)
3- Install Clang and LLD 9.0 or later
Compilation :
$ git clone https://github.com/CodeIntelligenceTesting/jazzer
$ cd jazzer
$ ./bazelisk-linux-amd64 run //:jazzer
Starting local Bazel server and connecting to it...
INFO: Analyzed target //:jazzer (79 packages loaded, 1410 targets configured).
INFO: Found 1 target...
Target //:jazzer up-to-date:
bazel-bin/jazzer
INFO: Elapsed time: 43.920s, Critical Path: 7.21s
INFO: 83 processes: 4 internal, 79 linux-sandbox.
INFO: Build completed successfully, 83 total actions
INFO: Build completed successfully, 83 total actions
driver/jazzer_driver: error while loading shared libraries: libjvm.so: cannot open shared object file: No such file or directory
We have a error
libjvm.so: cannot open shared object file: No such file or directory
If you have this error for solution we should define LD_LIBRARY_PATH
$ wget https://enos.itcollege.ee/~jpoial/allalaadimised/jdk15/jdk-15.0.2_linux-x64_bin.tar.gz
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ubuntu/jdk-15.0.2/lib/server/
$ ./bazelisk-linux-amd64 run //:jazzer
INFO: Analyzed target //:jazzer (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:jazzer up-to-date:
bazel-bin/jazzer
INFO: Elapsed time: 0.205s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Build completed successfully, 1 total action
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
INFO: Loaded 8 hooks from com.code_intelligence.jazzer.sanitizers.Deserialization
INFO: Loaded 1 hooks from com.code_intelligence.jazzer.sanitizers.ReflectiveCall
Missing argument --target_class=<fuzz_target_class>
Choose your java lib or code for fuzzing (Ex : generex)
1- Add "com.github.mifmif:generex:1.0.2"
lib to nano maven.bzl
load("@rules_jvm_external//:specs.bzl", "maven")
JAZZER_API_VERSION = "0.10.0"
JAZZER_API_COORDINATES = "com.code-intelligence:jazzer-api:%s" % JAZZER_API_VERSION
# **WARNING**: These Maven dependencies have known vulnerabilities and are only used to test that
# Jazzer finds these issues. DO NOT USE.
MAVEN_ARTIFACTS = [
"junit:junit:4.12",
"org.apache.commons:commons-imaging:1.0-alpha2",
"com.mikesamuel:json-sanitizer:1.2.1",
"com.google.code.gson:gson:2.8.6",
"com.fasterxml.jackson.core:jackson-core:2.12.1",
"com.fasterxml.jackson.core:jackson-databind:2.12.1",
"com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.12.1",
"com.alibaba:fastjson:1.2.75",
"com.beust:klaxon:5.5",
"javax.validation:validation-api:2.0.1.Final",
"javax.xml.bind:jaxb-api:2.3.1",
"javax.el:javax.el-api:3.0.1-b06",
"org.hibernate:hibernate-validator:5.2.4.Final",
"com.github.mifmif:generex:1.0.2",
maven.artifact("org.apache.logging.log4j", "log4j-api", "2.14.1", testonly = True),
maven.artifact("org.apache.logging.log4j", "log4j-core", "2.14.1", testonly = True),
]
2- Editing $ nano examples/BUILD.bazel
to this :
java_fuzz_target_test(
name = "GenerexFuzzer",
srcs = [
"src/main/java/com/example/GenerexFuzzer.java",
],
target_class = "com.example.GenerexFuzzer",
deps = [
"@maven//:com_github_mifmif_generex",
],
)
3- Create java file for fuzzing GenerexFuzzer.java
$ nano /home/jazzer/examples/src/main/java/com/example/GenerexFuzzer.java
Add my code for fuzzing by Jazzer
package com.example;
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.mifmif.common.regex.Generex;
// Found the issues.
public class GenerexFuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
try {
Generex generex = new Generex(data.consumeRemainingAsString());
generex.random();
} catch (IllegalArgumentException ignored) {
}
}
}
4- Now starting for fuzzing :
$ ./bazelisk-linux-amd64 run //examples:GenerexFuzzer
INFO: Analyzed target //examples:GenerexFuzzer (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //examples:GenerexFuzzer up-to-date:
bazel-bin/examples/GenerexFuzzer
INFO: Elapsed time: 0.121s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Build completed successfully, 1 total action
exec ${PAGER:-/usr/bin/less} "$0" || exit 1
Executing tests from //examples:GenerexFuzzer
-----------------------------------------------------------------------------
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
INFO: Loaded 8 hooks from com.code_intelligence.jazzer.sanitizers.Deserialization
INFO: Loaded 1 hooks from com.code_intelligence.jazzer.sanitizers.ReflectiveCall
INFO: Loaded 8649 no-throw method signatures
INFO: Instrumented com.example.GenerexFuzzer (took 42 ms, size +37%)
INFO: libFuzzer ignores flags that start with '--'
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2735196724
INFO: Loaded 1 modules (512 inline 8-bit counters): 512 [0x7fcec02c9010, 0x7fcec02c9210),
INFO: Loaded 1 PC tables (512 PCs): 512 [0x7fce8abfe010,0x7fce8ac00010),
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: Instrumented com.mifmif.common.regex.Generex (took 16 ms, size +49%)
INFO: Instrumented com.mifmif.common.regex.util.Iterable (took 1 ms, size +0%)
INFO: Instrumented com.mifmif.common.regex.util.Iterator (took 0 ms, size +0%)
INFO: New number of inline 8-bit counters: 1024
INFO: Instrumented dk.brics.automaton.RegExp (took 17 ms, size +104%)
INFO: Instrumented dk.brics.automaton.RegExp$Kind (took 2 ms, size +42%)
INFO: Instrumented dk.brics.automaton.RegExp$1 (took 1 ms, size +102%)
INFO: Instrumented dk.brics.automaton.BasicAutomata (took 11 ms, size +130%)
INFO: New number of inline 8-bit counters: 2048
INFO: Instrumented dk.brics.automaton.Automaton (took 9 ms, size +82%)
INFO: Instrumented dk.brics.automaton.State (took 2 ms, size +55%)
INFO: Instrumented dk.brics.automaton.Transition (took 2 ms, size +74%)
INFO: Instrumented dk.brics.automaton.TransitionComparator (took 1 ms, size +97%)
INFO: A corpus is not provided, starting from an empty corpus
#2 INITED cov: 71 ft: 71 corp: 1/1b exec/s: 0 rss: 114Mb
#3 NEW cov: 176 ft: 191 corp: 2/3b lim: 4 exec/s: 0 rss: 114Mb L: 2/2 MS: 1 CopyPart-
#5 NEW cov: 178 ft: 286 corp: 3/6b lim: 4 exec/s: 0 rss: 114Mb L: 3/3 MS: 2 ChangeByte-InsertByte-
#10 NEW cov: 178 ft: 378 corp: 4/10b lim: 4 exec/s: 0 rss: 114Mb L: 4/4 MS: 5 InsertByte-ChangeBit-ChangeBinInt-InsertByte-CopyPart-
#21 NEW cov: 181 ft: 384 corp: 5/13b lim: 4 exec/s: 0 rss: 114Mb L: 3/4 MS: 1 ChangeBit-
#6375 NEW cov: 975 ft: 4248 corp: 243/1071b lim: 8 exec/s: 6375 rss: 154Mb L: 7/8 MS: 1 CrossOver-
#6391 NEW cov: 975 ft: 4250 corp: 244/1079b lim: 8 exec/s: 6391 rss: 154Mb L: 8/8 MS: 1 CopyPart-
== Java Exception: com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow: Stack overflow (truncated to likely cause)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
Caused by: java.lang.StackOverflowError
at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.base/java.util.TimSort.sort(TimSort.java:220)
at java.base/java.util.Arrays.sort(Arrays.java:1232)
at dk.brics.automaton.State.getSortedTransitionArray(Unknown Source)
at dk.brics.automaton.State.getSortedTransitions(Unknown Source)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:340)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
at com.mifmif.common.regex.Generex.prepareRandom(Generex.java:366)
LibFuzzer crashing input :
MS: 2 ChangeBit-CMP- DE: "\x00\x00\x00\x05"-; base unit: b5d43fd7e3064418d903c4d27d2238f390e23c62
0x7e,0x2f,0x7d,0x0,0x0,0x0,0x5,
~/}\x00\x00\x00\x05
artifact_prefix='/root/.cache/bazel/_bazel_root/c82b104c68f93e19e57160becd18f8f0/execroot/jazzer/bazel-out/k8-opt/testlogs/examples/GenerexFuzzer/test.outputs/'; Test unit written to /root/.cache/bazel/_bazel_root/c82b104c68f93e19e57160becd18f8f0/execroot/jazzer/bazel-out/k8-opt/testlogs/examples/GenerexFuzzer/test.outputs/crash-101076ac3391a62fb4622589093c2543063de037
Base64: fi99AAAABQ==
Congratulations! We found Stack overflow
Vulnerability.
I hope enjoy,
Thanks, Ramin
Top comments (2)
Wow Thank You Ramin for the great example on how fuzzing can support finding voulnerabilities early on in the development process! Great Read!
๐