Improving Security with Fuzzing and Sanitizers

Hanno Böck
https://hboeck.de/
https://fuzzing-project.org/

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)

-fsanitize=address

#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");
	free(a);
	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

Results

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

-fsanitize=undefined

Memory Sanitizer

-fsanitize=memory

Thread Sanitizer

-fsanitize=thread
- -------------------------------------------------------------------------
Debian Security Advisory DSA-3775-1                   security@debian.org
https://www.debian.org/security/                       Moritz Muehlenhoff
January 29, 2017                      https://www.debian.org/security/faq
- -------------------------------------------------------------------------

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 
                 CVE-2017-5486

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.

Fuzzing

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-fuzz

AFL has revolutionized Fuzzing

AFL finds bugs everywhere

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

AFL + ASAN

Use them together to find more bugs

LibFuzzer

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);
  free(buf);
  free(inp);
  return 0;
}

Demo

LibFuzzer and c-ares

LibFuzzer

Advantage: Faster

Disadvantage: More work

Heartbleed

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

Experiment

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.

Bugs

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)

Example

Automatically own Linux Desktop via bug in Nintendo Sound File emulator from Gstreamer through web page
https://scarybeastsecurity.blogspot.com/2016/11/0day-exploit-compromising-linux-desktop.html

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.

Conclusion

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

Conclusion

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

Conclusion

All these tools are free, please use them

Thanks for listening!

Questions?
https://fuzzing-project.org/
https://hboeck.de/