8

Use-after-free bugs are a particular class of memory safety bugs. How often are they exploitable, in practice? When you find a use-after-free bug in a program, is it often exploitable, rarely exploitable, or does it vary based upon some other factor I'm overlooking?

I'm particularly interested in how often use-after-free bugs in C programs are exploitable (specifically, C, rather than C++). How often are use-after-free bugs in C programs exploitable? If I discover a use-after-free bug in a C program I'm testing, what should I estimate as the likelihood it is exploitable? 90%? 50%? 10%? When triaging bugs (e.g., fuzzer crashes, Valgrind warnings, warnings from static analysis tools), how highly should I prioritize fixing use-after-free bugs, compared to other kinds of memory safety bugs?


Research I've done. I have been doing some research. It looks like use-after-free bugs in C++ programs are often exploitable (because the memory layout of a C++ object always contains a pointer to a vtable, and overwriting this leads easily to code injection). OK, good. Now what about C programs?

I can also see how use-after-free bugs can be exploited in certain special cases. For instance, use-after-free bugs in browsers or other programs with user-controllable scripting seem to often be exploitable, because of the ease of doing heap spraying and the great deal of control over the contents of objects stored in memory. And, yes I've seen some sophisticated methods of exploiting use-after-free bugs in certain special cases (e.g., using them for information disclosure, which then lets you derandomize ASLR, after which....), but those seem pretty application-specific and like you might need to get lucky for the attack to work and even then it'd take a bunch of work to build the exploit. But I'm interesting in knowing what the "typical case" usually looks like, rather than the special cases where the attacker gets lucky.

D.W.
  • 98,420
  • 30
  • 267
  • 572

1 Answers1

2

Use-after-free attacks require the attacker to be able to allocate some memory reliably on heap.

Say I have an object that takes 16 bytes, and happens to be allocated in memory to 0xb00000004 (completely made up numbers here). I delete this object and the memory is returned to the heap. Now I request another heap allocation for 16 bytes (a string for example) and the heap allocates it on 0xb0000004. Now a pointer referencing the old object instead calls the new object, not even realizing it.

As you've previously mentioned, this is popular with scripting languages for a reason. That reason is because scripting languages can reliably allocate memory on the heap.

Therefore to know if you're going to be vulnerable, you need to assess how difficult it would be for an attacker to be able to allocate memory, and if that attacker could allocate it reliably.

In a C program, the potential risk appears to be less since any such pointers or references are going to be on basic data types, not objects. How is an attacker going to execute arbitrary code when the program treats it as data instead? In that case you need to analyze if your data can be trusted.

For example, let's say your program stores a string "http://xyz.com/super program.zip", and you have code to download, extract, and execute it. If an attacker is somehow able to overwrite that string to http://superbadplace.com/supervirus.zip/", then your program could unintentionally be installing a shell.

forest
  • 64,616
  • 20
  • 206
  • 257