Stream: wg-secure-code

Topic: automated fuzzing of stdlib

Shnatsel (Oct 26 2018 at 14:00, on Zulip):

Speaking of which. I have an idea for a project that could significantly improve Rust stdlib security - I want to auto-generate fuzzing harnesses for Rust stdlib functions and run fuzzing on them. This would have discovered the previous CVE in Rust stdlib before it escaped into the wild. But to be effective this would need to run repeatedly because so far both Rust stdlib CVEs were introduced during refactoring. Maybe not run in CI, that'd be too expensive, but once per beta release or some such. @qmx would it be okay to ping you about resources to run this on if I actually get around to hacking this together?

qmx (Oct 26 2018 at 15:00, on Zulip):

I can always ask, we already have NO as the default response :stuck_out_tongue:

Joshua Liebow-Feeser (Oct 26 2018 at 17:19, on Zulip):

Google already has a project for this, and this sounds like a good fit:

Shnatsel (Oct 26 2018 at 19:14, on Zulip):

I am aware of oss-fuzz, but what I'm trying to do is rather different from the traditional fuzzer integration, and does not really fit that that mold. However, after reading up on it a bit more, I think integrating with oss-fuzz might be feasible. The big question is whether it will work with Rust code at all - it only officially supports C and C++.

Joshua Liebow-Feeser (Oct 26 2018 at 19:44, on Zulip):

Ah. I don't know anything about oss-fuzz other than that it exists, so I can't be of much help here. I could try finding folks internally and putting you in touch with them if you want, though.

Shnatsel (Oct 26 2018 at 19:52, on Zulip):

That'd be stellar! It's a little early for that, though, but thanks for the offer! And I figure I'll try the regular channels first.
I'm starting a job at Google myself in two weeks but I don't know what degree of access to those folks it will get me, if any.

Joshua Liebow-Feeser (Oct 26 2018 at 19:52, on Zulip):

It will get you plenty of access. Not that there's not access to the public - just that it's easier to find out who they are if you can search internal documentation.

Joshua Liebow-Feeser (Oct 26 2018 at 19:53, on Zulip):

Before I was at Google, I had a number of good experiences tracking down people who'd published a white paper or a product or something and getting them on GVC to ask them for advice on stuff.

Shnatsel (Oct 26 2018 at 19:53, on Zulip):

Well, I've been in touch with the author of AFL-fuzz before. What's GVC?

Joshua Liebow-Feeser (Oct 26 2018 at 19:54, on Zulip):

Google Video Chat. I think it's an old name for the video chat aspect of Google Hangouts? I'm not really sure; it's just an acronym people use.

Alex Gaynor (Oct 26 2018 at 21:11, on Zulip):

I'm very familiar with oss-fuzz, I've done a bunch of integrations. It should handle Rust fine, though the existing CFLAGS/CC handling obviously won't help at all. The big challenge for your work is that the "unit of integration" for OSS-Fuzz by default is a libFuzzer entrypoint. So if you can structure your work in terms of a function that takes a &[u8], it'll be Just A Matter Of Engineering. Otherwise work will be required.

Shnatsel (Oct 26 2018 at 21:28, on Zulip):

Nice. I have a prototype for fuzzing the function with Rust stdlib's latest CVE that just accepts &[u8] as input. This is how it looks. Automatically generating such things for other functions should be fairly trivial, there are literally 3 lines that are specific to the function in the entire file.
Sadly, in my tests this harness has failed to discover the vulnerability. I guess that's because I've been fuzzing on 64-bit, where most of the address space gets you OOM killed instantly. I should try it on 32-bit. I've tried getting a 32-bit chroot in Docker going to make the results reproducible, but I couldn't figure out how to get a 32-bit Docker container on a 64-bit machine without just copy-pasting the entire dockerfile for the base 32-bit image.

Alex Gaynor (Oct 26 2018 at 21:33, on Zulip):

Just so I understand this code, the input you're getting is just returned by the RNG as you request entropy from it -- not hashed and used as a seed or anything?

Joshua Liebow-Feeser (Oct 26 2018 at 21:37, on Zulip):

Slightly off-topic: Does oss-fuzz or the Rust fuzzing harnesses you've been using support coverage-guided fuzzing?

Shnatsel (Oct 26 2018 at 21:46, on Zulip):

I've been only using coverage-guided fuzzing, the rest of it is vastly inferior and pretty useless. AFL, libfuzzer, honggfuzz are all coverage-guided, although honggfuzz did not start out that way.

Alex Gaynor (Oct 26 2018 at 21:46, on Zulip):

OSS-Fuzz is exclusively coverage guided fuzzing; it's libFuzzer + AFL

Alex Gaynor (Oct 26 2018 at 21:47, on Zulip):

(Technically that's not true, they have special cases for fuzzing SpiderMonkey, JSC, and Chakra which use a custom non-coverage guided fuzzer. But it's basically true.)

Joshua Liebow-Feeser (Oct 26 2018 at 21:47, on Zulip):

OK cool

Shnatsel (Oct 26 2018 at 21:48, on Zulip):

so like but without the coverage feedback?

Alex Gaynor (Oct 26 2018 at 21:49, on Zulip):

No, it's a custom javascript fuzzer based on merging and mutating snippets from existing JS programs.

Shnatsel (Oct 26 2018 at 21:51, on Zulip):

prog-fuzz is basically a completely custom mutation strategy on top of AFL instrumentation feedback. Combining your custom mutation strategy with instrumentation feedback would probably get you better results, although you'd need a pretty big map size or use the (unreleased) coll-afl fork for such a big codebase to be manageable.
Actually, doesn't Mozilla maintain a fork of AFL that lets you plug in custom mutation strategies using Python?

Alex Gaynor (Oct 26 2018 at 21:52, on Zulip):

I know that's something our fuzzing team used, dunno if we still work on it or not.

Shnatsel (Oct 26 2018 at 21:55, on Zulip):

As for the code I've linked - I've tried to get it to use the input as-is as much as possible, but at the same time I've tried to reuse the "arbitrary" trait made for QuickCheck that transforms &[u8] into structures like strings which is geared towards PRNG output as input. So there's some boilerplate wrapping the input &[u8] and pretending it's PRNG output. I'm still not 100% sure that it doesn't do weird things like hashing to the input, but I've tried to eliminate that.

Shnatsel (Oct 26 2018 at 22:11, on Zulip):

Okay, that was actually a really good question that prompted me to looked at the implementation of Arbitrary and supporting traits. Now I think I know what might be throwing off the fuzz harness. QuickCheck RNG wrapper accepts a size parameter that controls both the length of the generated strings and range of generated numbers, at the same time. This means that when I set it really high which is needed to generate a large number and trigger an overflow, it simply tries to generate a large string and fails because the size of fuzzer input is a few gigabytes short.

Shnatsel (Nov 04 2018 at 10:52, on Zulip):

@Stuart Small now that you're toying with syn, this thread is about a fairly simple but important project I've been meaning to get around to, but so far couldn't. It might be of interest to you. If you'd like to collaborate on this, I could handle the fuzzer part and let you have fun with syn

Stuart Small (Nov 04 2018 at 18:17, on Zulip):

Oh man, Great news. I was really enjoying syn and looking forward to more with it. I'll catch up on this thread

Shnatsel (Nov 04 2018 at 18:18, on Zulip):

Neat! I probably didn't describe what I'm trying to do in sufficient detail so feel free to ping me

Stuart Small (Nov 04 2018 at 18:18, on Zulip):

Will do.

Shnatsel (Nov 10 2018 at 21:22, on Zulip):

@Stuart Small I'll have tomorrow and the day after mostly free, so I'll probably be taking another stab at the automated fuzzing of stdlib, at the parts that do not involve syn because I still haven't looked into it. I should be available all day (in UTC+1 timezone) if you want to collaborate and/or have any questions.

Shnatsel (Jan 22 2019 at 02:09, on Zulip):

Okay, so, I've taken another stab at auto-generating fuzzing harnesses for functions based on type declarations. I have done the "parse the functions and methods and get types from them" part, it also converts the data into an intermediate representation that's convenient for fuzzing. I've also implemented pretty-printing for the intermediate representation. It parses the entire stdlib without panicking, so that's something. Haven't tried writing the generation pass yet, but judging by the template it should not be all that hard.
Stuff like &str will give me trouble because it has no direct constructor, I'll have to special-case them.
I'm also concerned about use statements, but perhaps there is an "expand everything" output from the compiler that turns them from relative to absolute? Visibility would probably still be an issue though.

Shnatsel (Feb 09 2019 at 20:32, on Zulip):

I've applied for copyright release for this project but got denied. This means that if I open-source it, it will come with a Google CLA attached, which includes copyright assignment among other things:

There are two paths from here:
1. Bite the bullet and attach the CLA to the project forever. I fear this would have a detrimental effect on the number of contributions, but I'd be interested to hear what you guys think.
2. Get somebody outside Google to kick off the project based on public info. Since I've published the idea and a good chunk of implementation before I joined Google, the only thing the company has a claim to is ~40 lines of code that parse function definitions into structs and pretty-print those structs. So if somebody could re-implement that, I could join in afterwards and we'd have a non-CLA'd project.
Frankly gets you most of the way there for parsing, and we can drop the pretty-printing.

The question is: are there any takers for option 2?

Tony Arcieri (Feb 11 2019 at 06:35, on Zulip):

@Shnatsel so on a not-entirely-unrelated note I saw Google open sourced clusterfuzz

Tony Arcieri (Feb 11 2019 at 06:35, on Zulip):

could... that be used for this? I don't really know, just spitballing

Shnatsel (Feb 16 2019 at 22:03, on Zulip):

Well, @blt of bughunt-rust fame considers it useful. Frankly I haven't looked into it.

Shnatsel (Feb 16 2019 at 22:14, on Zulip):

Also, @Eh2406 has independently implemented all parts of automated fuzzing harness generator that I was not allowed to release. I actually like their architecture more than mine. The code is now public and resides here:
It is already useful for generating proptest boilerplate - it gets you 80% there so you can focus on the stuff that matters.
I'll be hacking on it in my spare time, mostly weekends. A coworker of mine has expressed interest in the project just this weekend, and unlike me he has some professional security experience. I hope he will join in soon as well.

Tony Arcieri (Feb 17 2019 at 03:06, on Zulip):

whoa, that sounds awesome in theory

Shnatsel (Feb 17 2019 at 18:05, on Zulip):

I just keep discovering more and more stuff that I've inspired:
I might actually use this, too.

Tony Arcieri (Feb 17 2019 at 21:34, on Zulip):

heh fun... almost thought it might be useful to me but I was thinking no_std which that crate definitely isn't

Shnatsel (Feb 17 2019 at 21:42, on Zulip):

Okay, so the initial implementation is in. Currently parses a hardcoded string, but the generated code should at least compile and maybe even find some bugs.

Shnatsel (Feb 17 2019 at 21:51, on Zulip):

It's too early to actually try using it, but hey, at least I'm making progress and shouldn't face any more legal hurdles

Shnatsel (Feb 17 2019 at 21:55, on Zulip):

In other fuzzing-related news: png crate authors didn't implement fuzzing on CI, so the crate has regressed and you can OOM-crash it again.
And I've dug up another vulnerability on rustc bug tracker that should have got a CVE, but didn't. Reported to Rust security team.

Tony Arcieri (Feb 17 2019 at 22:02, on Zulip):


Shnatsel (Feb 18 2019 at 22:42, on Zulip):

I kid you not

Shnatsel (Feb 18 2019 at 22:43, on Zulip):

Also, this project is looking for a name:

Stuart Small (Feb 18 2019 at 23:48, on Zulip):

rust fleece. It's all sorts of fuzzy hehe

Gerardo Di Giacomo (Feb 19 2019 at 17:36, on Zulip):

for fuzzing there's also ( - not sure if it was mentioned

Stuart Small (Feb 19 2019 at 17:54, on Zulip):

I'm planning on adding a section to that explaining how to use arbitrary in fuzz tests. I wanna get a little more practice with it first so I don't add bad docs

Shnatsel (Feb 19 2019 at 19:10, on Zulip):

Using Arbitrary is exactly the approach I'm taking with the automated generator. I'm not sure if it's worth the trouble in case you have 1-2 harnesses, though. It's probably easier to construct the data type ad-hoc instead of bringing in all the complexity of Arbitrary, most of which is not necessary anyway.

Shnatsel (Feb 19 2019 at 19:14, on Zulip):

"fleece" is cool but both "cargo fleece" and "fleece fuzz" GOogle searches produce over a million results

Gerardo Di Giacomo (Feb 19 2019 at 19:41, on Zulip):

libfuzzer already has an automated generator, why not using that ?

Shnatsel (Feb 19 2019 at 19:45, on Zulip):

Huh? Automated generator of what? Last time I checked cargo-fuzz only created a project template, similar to cargo new. Did I overlook something?

Gerardo Di Giacomo (Feb 19 2019 at 21:21, on Zulip):

I've been using both afl and libfuzzer (mostly for testing for now - nothing serious), libfuzzer doesn't require a corpus to start working, but you can provide one and then it does the mutations (like afl)

Gerardo Di Giacomo (Feb 19 2019 at 21:24, on Zulip):

as far as names, how about the name of a fuzzy crab? :P

Gerardo Di Giacomo (Feb 19 2019 at 21:24, on Zulip):


Shnatsel (Feb 19 2019 at 21:31, on Zulip):

Oh yeah, it's not about generating the corpus, afl/libfuzzer/honggfuzz handle that already. It's about generating the glue code that reads bytes from afl/libfuzzer/honggfuzz and feeds them to the function you want to fuzz, automatically and for every function in the library.

Shnatsel (Feb 19 2019 at 21:36, on Zulip):

"Hirtellus" is pretty uniqie, "cargo hirtellus" or "hirtellus fuzz" don't turn up many results. Googling "hirtellus" alone turns up a ton of results for a plant, though.

Shnatsel (Feb 19 2019 at 21:37, on Zulip):

"fuzzbiglib" without quotes is 0 results, so that's also an option

Shnatsel (Feb 19 2019 at 21:38, on Zulip):

I wonder if there is a library pun in here somewhere? I have no clue what book storage procedures look like, though.

Shnatsel (Feb 19 2019 at 21:39, on Zulip):

the best I've got is "fuzzandria" which is 2 results in google without quotes

Gerardo Di Giacomo (Feb 19 2019 at 21:47, on Zulip):

Oh yeah, it's not about generating the corpus, afl/libfuzzer/honggfuzz handle that already. It's about generating the glue code that reads bytes from afl/libfuzzer/honggfuzz and feeds them to the function you want to fuzz, automatically and for every function in the library.


Gerardo Di Giacomo (Feb 19 2019 at 23:53, on Zulip):

@Shnatsel have you tried to upgrade libfuzzer to master with cargo fuzz?

maksimsco (Feb 21 2019 at 04:49, on Zulip):

@Shnatsel why do you think nobody runs fuzzing on CI, is it too cumbersome or something?

Daniel Carosone (Feb 21 2019 at 04:59, on Zulip):

is it maybe to do with wanting repeatable test results (which fuzzing generally isn't if you randomise generation), or that you have a different interpretation of "test failure" (where someone needs to look over results)? Unless you can have a relatively simple criterion (fuzz for N mins with no panics), it doesn't fit CI workflow well.

Daniel Carosone (Feb 21 2019 at 05:00, on Zulip):

to put it another way, perhaps CI is not a good place for a project to start fuzzing. Maybe once they've got a mature set of cases and robust error handling, they can CI fuzzing for regressions.

Alex Gaynor (Feb 21 2019 at 05:04, on Zulip):

I think the clusterfuzz model of continuous fuzzing that's seperate from CI, and then running all your regression test cases in CI makes more sense personally.

Shnatsel (Apr 21 2019 at 20:25, on Zulip):

A quick update: still working on on and off, but the progress is slow. There is a fork that adds a bunch of useful stuff, I need to drop the latest commit from it which is kinda misguided and then pull it in.

Shnatsel (Apr 21 2019 at 20:26, on Zulip):

Also maybe comment the code better to make it more approachable, it's kind of a mess right now.

Last update: Nov 11 2019 at 22:50UTC