Improving Security with Fuzzing and Sanitizers

Hanno Böck

The Fuzzing Project

Core Infrastructure Initiative

Bug in KeepassXC / zxcvbn-c

String of 48 bytes length

    uint8_t PossChars[48];

Buffer Overflow

Code used in a security tool (zxcvbn-c), bundled by another security tool (Keepass XC), had a buffer overflow on startup.

Why did nobody notice?

Samba bugs

	TDB_DATA tdbkey = { .dptr = (uint8_t *)&key, .dsize = sizeof(key) };
	TDB_DATA tdbdata = { .dptr = (uint8_t *)&key, .dsize = sizeof(rec) };
if (msg[len - 1] == '\n') {

Samba bugs

Buffer overread and buffer overflow during make check.

One more buffer overread when trying to access samba share.

How did I find these bugs?

And why did nobody else?

Address Sanitizer (ASAN)


#include <stdio.h>
int main() {
	int a[3] = { 2, 1, 0 };
	a[3] = 5;
	printf("%i\n", a[3]);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
	char* a;
	a = malloc(strlen("test"));
	strcpy(a, "test");
	printf("%s\n", a);

Address Sanitizer

Powerful tool to find memory safety bugs in C / C++
If you maintain C code there's no excuse not to test it with Address Sanitizer
If ASAN finds all these bugs - could we build a complete system with ASAN?

Gentoo + ASAN

Linux system with everything ASAN-enabled


Found bugs in Bash, Coreutils/Shred, man-db, Pidgin-OTR, Courier, Syslog-NG, Screen, Claws-Mail, ProFTPD ICU, TCL, Dovecot, Glib, GNOME, Qt, KDE, Libarchive, Squid, CMake, Gettext, SpamAssassin, Monit, lvm2, ...

Other Sanitizers

Undefined Behavior Sanitizer


Memory Sanitizer


Thread Sanitizer

- -------------------------------------------------------------------------
Debian Security Advisory DSA-3775-1                                Moritz Muehlenhoff
January 29, 2017            
- -------------------------------------------------------------------------

Package        : tcpdump
CVE ID         : CVE-2016-7922 CVE-2016-7923 CVE-2016-7924 CVE-2016-7925 
                 CVE-2016-7926 CVE-2016-7927 CVE-2016-7928 CVE-2016-7929 
                 CVE-2016-7930 CVE-2016-7931 CVE-2016-7932 CVE-2016-7933 
                 CVE-2016-7934 CVE-2016-7935 CVE-2016-7936 CVE-2016-7937 
                 CVE-2016-7938 CVE-2016-7939 CVE-2016-7940 CVE-2016-7973 
                 CVE-2016-7974 CVE-2016-7975 CVE-2016-7983 CVE-2016-7984 
                 CVE-2016-7985 CVE-2016-7986 CVE-2016-7992 CVE-2016-7993 
                 CVE-2016-8574 CVE-2016-8575 CVE-2017-5202 CVE-2017-5203 
                 CVE-2017-5204 CVE-2017-5205 CVE-2017-5341 CVE-2017-5342 
                 CVE-2017-5482 CVE-2017-5483 CVE-2017-5484 CVE-2017-5485 

Multiple vulnerabilities have been discovered in tcpdump, a command-line
network traffic analyzer. These vulnerabilities might result in denial
of service or the execution of arbitrary code.


Test software with invalid inputs, see if it crashes

Dumb fuzzing

Take valid input, add random errors

Template-based fuzzing

Create fuzzer for particular file format or protocol

Coverage-based fuzzing

Fuzzer detects inputs that trigger new code paths

American Fuzzy Lop (AFL)


AFL has revolutionized Fuzzing

AFL finds bugs everywhere

OpenSSL, OpenSSL, Apache, libjpeg-turbo, libpng, sqlite, GnuPG, Bash, BIND, NTPD, Stagefright, ...


Use them together to find more bugs


AFL tests executables

LibFuzzer tests functions

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/nameser.h>
#include <ares.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  unsigned char *buf;
  int buflen;
  char *inp = (char *)malloc(size + 1);
  inp[size] = 0;
  memcpy(inp, data, size);
  ares_create_query((const char *)inp, ns_c_in, ns_t_a, 0x1234, 0, &buf,
                    &buflen, 0);
  return 0;


LibFuzzer and c-ares


Advantage: Faster

Disadvantage: More work


Can we find a bug like Heartbleed with Fuzzing?

Caveat: Heartbleed was found with fuzzing once, but with a specialized TLS fuzzer that is not publicly available


Create handshake fuzzer for OpenSSL, run with AFL + ASAN

AFL finds Heartbleed after ~ 6 hours.

LibFuzzer is way faster (~ 5 minutes).

Differential Fuzz Testing

Crypto is math

But is the math correct?

Bugs in the math can be devastating

RSA-CRT bug: Wrong calculation of modular exponentiation reveals private key

Fuzzing Math

Same calculation with two different implementations.

Compare output, assert if results differ.


OpenSSL / BN_mod_exp (CVE-2015-3193)

Nettle / ECC (CVE-2015-8803, CVE-2015-8804)

NSS / mp_div() / mp_exptmod() (CVE-2016-1938)

OpenSSL / Poly1305

MatrixSSL / pstm_exptmod (CVE-2016-6885, CVE-2016-6886, CVE-2016-6887)

Attack surface on the Linux Desktop

Owning the Linux Desktop

Step 1: Some browsers download files automatically (e.g. Chrome / Chromium)
Step 2: Desktop search tools (GNOME Tracker / KDE Baloo) automatically index files
Step 3: Exploit a bug in one of those parsers (there are many parsers with little or no security vetting)


Automatically own Linux Desktop via bug in Nintendo Sound File emulator from Gstreamer through web page

Automatic parsers

The Linux Desktop exposes lots of very low quality C code to untrusted input

Desktop search and thumbnailer

GNOME has sandboxed them now.
KDE has not.


For good reasons people want to get rid of C/C++, but there's still a lot of C code we depend upon


A combination of Sanitizers and smart Fuzzing is able to discover a large chunk of C-related bugs


All these tools are free, please use them

Thanks for listening!