Go or No Go: Differential Fuzzing of Native and C Libraries
Abstract
In little more than a decade, Go has become one of the most popular programming languages in use today. It is a statically-typed, compiled language with spatial and temporal memory safety achieved by way of strong typing, automatically inserted bounds checks, and a mark-and-sweep garbage collector. Go developers can make immediate use of a large set of native libraries, whether shipped as part of the runtime or available to be imported from community code. Alternatively Go developers can directly link to C/C++ libraries which can be called from Go sources thanks to cgo functionality. Factors that go into this decision are stability, performance, and availability. As a result developers have a choice between Go native libraries or non-native code. However, today there is little understanding how to consider security implications in this decision. Our work is the first to investigate security implications of choosing between native and non-native libraries for Go programs. We first investigate to what extent popular GitHub projects make use of cgo, revealing that this choice is in fact quite popular. We then design and build a differential fuzzer that can compare native and C/C++ implementations of the same functionality. We implement the fuzzer and test its effectiveness on four popular packages (libcrypto, libpng, libssl, and libz), describing the results and highlighting their security impact. Finally, we present two real-world case studies (anti-virus evasion including the anti-virus scanner included in Gmail plus Certificate Transparency case study) and discuss how our differential fuzzer discovered implementation differences with security impact. Our work has led to changes in Golang zlib which have since shipped.