Break Your Android Build…

…before your customers or adversaries do. How? Feel the fuzz buzz! In this post, you will learn the basics how to use white box fuzzing with cifuzz integrated into Gradle, so you can test your code deep and early in your dev cycle.

David Merian
ProAndroidDev

--

This is a basic tutorial on fuzzing in Gradle, and you may need to consult additional resources. There are many testing approaches, but the later bugs are found in the SDLC (software development lifecycle), the more difficult and expensive they are to fix. These bugs or security issues may be left unfixed for an undesirable amount of time, increasing risk or compromising the user experience. If you want to shift left, that is, find bugs and vulnerabilities very early—like in your IDE—then you will want to try white box fuzzing.

I will start by briefly explaining how fuzzing works, and then describe the setup of the fuzzing tool for Gradle. Feel free to skip the first section to get to the practical explanation.

Photo by Adrien on Unsplash

Fuzz What?

Fuzzing is a code testing technique, whereby random, unexpected, and invalid inputs are sent to the software under test many times per second. On the one hand, fuzzing can be “dumb”, where it doesn’t mutate its inputs based on feedback on the application (akin to brute force attacks). On the other hand, fuzzing can be “smart,” where it does mutate its inputs based on the feedback from the software under test and has access to the source code, thereby providing code coverage metrics.

Today, we are talking about a smart fuzzer, cifuzz. This fuzzer will give you code coverage by instrumenting the code. It will find bugs, crashes, and security vulnerabilities in your android build by running thousands of tests cases a second, and then saving the successful code paths in a corpus, so that it becomes more efficient with each successive run.

The results of fuzzing are considered high value, because the fuzzer is executing the code in runtime, rather than the approach like static analysis, which can generate many false positives.

Google is a wide supporter of fuzzing through its in-house development and OSS-Fuzz project. Fuzzing has found thousands of bugs and security vulnerabilities in a wide variety of projects.

Fuzzing is a testing and QA technique that uses random, unexpected, and invalid inputs to find bugs and issues in software. Photo by Michael Dziedzic on Unsplash

Fuzz Gradle?

In this section, I will explain how you can setup cifuzz in your gradle build system and run the fuzzer to find bugs. This is a basic tutorial on fuzzing, and you may need to consult additional resources.

cifuzz is a CLI tool that helps you to integrate and run fuzzing based tests into your project. If you are using Gradle, add this plugin to your build.”

1. Start

To use the cifuzz Gradle plugin, you first need to apply the plugin in build.gradle or build.gradle.kts for the files of the project. This project should contain fuzz tests in cifuzz.yaml (which is generated with the command cifuzz init, more info for using cifuzz here).

You can find this file in root for a single project, whereas it is located in a subproject folder for multi-projects.

plugins {
id("com.code-intelligence.cifuzz") version "<<latest_version>>"
}

This setup can be used in airgapped / offline environments as well; details are here.

Make sure to check compatibility:

  • For JVM (Java, Kotlin, ...) projects, the minimum supported Gradle version is Gradle 6.1
  • For Android projects, 7.5 (Android Gradle Plugin 7.4) or 8.0 (Android Gradle Plugin 8.0) are the minimum supported Gradle version

2. Write a Fuzz Test

Using Jazzer and JUnit 5, the cifuzz Gradle plugin sets up everything to write and run fuzz tests. If you need help writing fuzz tests, Jazzer documentation will help you learn this. Then cifuzz will run the fuzz tests that you write. It will “run them directly as regression tests through Gradle.”

A simple property-based fuzz test could look like this (excluding imports):

class ParserTests {
@Test
void unitTest() {
assertEquals("foobar", SomeScheme.decode(SomeScheme.encode("foobar")));
}

@FuzzTest
void fuzzTest(FuzzedDataProvider data) {
String input = data.consumeRemainingAsString();
assertEquals(input, SomeScheme.decode(SomeScheme.encode(input)));
}
}

Note the default settings: the plugin expects your fuzz tests to be located in src/test. You may have to configure the settings, if your tests are in a separate test source set or test suite.

3. Android projects

For your Android projects, you can configure the androidVariant to run the fuzz tests. The default will be release. An example is

cifuzz {
androidVariant.set("fullDebug") // Set to variant for flavor=full and buildType=debug
}

Conclusion

There are a wide variety of testing techniques available, but to find issues early and identify edge cases, then you will want to try integrating white box fuzzing into your development process / devops pipeline. You will benefit by saving time in your development and shipping more robust products and features.

If anything in this write up was unclear, please drop me a line if you want more help or have questions.

--

--

Application Security Testing | Web Security | Embedded Security | DevSecOps | Fuzzing | Software Security | SaaS + OnPrem | ISO 21434 | Pentesting | #followback