This article is about use-after-free vulnerability, its mechanics and how it can be used for evil things. Several things could be done by using this vulnerability, for example, reading sensitive info or arbitrary code execution. The exploitation often requires the presence of some other vulnerability as well, for example, buffer overflow (not always).
Mechanics
Computer stores data in either of two places: heap or stack. The stack is relatively small, so only a little is stored there (although it does not mean any less valuable). While buffer overflow is more of a concern for the stack, this vulnerability is the heap’s π© headache.
So, imagine you have a pointer π» pointing to some π΄ object on the heap π© that will say, start doing good
. Some address space is allocated for this data structure, all good.
Now, the program thinks it doesn’t need that object anymore and says to the OS: “Hey, OS, you can choke on that address space, I don’t need it”. But the OS is not made of flimsy material and just says, “Eh, whatever, I am busy. Five minutes.”.
So, it just puts the broom π§Ή by the address space and forgets about it (“Why bother? when the space is needed, I will overwrite it”, it thinks.)
Now, another object is created, a π₯ beautiful rose. It carries a message “Cease doing good, start doing evil.”. The developer doesn’t intend to use its horrible and distructive function, but he only needs its petals. As it does for any other object, OS allocates new space for that π₯ object. But remember, it’s lazy. It doesn’t go far. What’s the last memory freed and thus the closest?
It does not mean that it will ALWAYS be the same address space, but the possibility of that can be increased, for example, if the attacker allocates a lot of room for their data. For the fun’s sake, let’s assume that we are sure that the address space newly allocated is the same.
Now, we create another object, new pointer pointing to the same location.
Now, asign the new value to this old-new location. Let’s say it now says “cease”. There is a new π₯ pointer now, which is pointing to the same location. The “start” gets overwritten. But the thing is that the first pointer π» is still pointing to this location. So, you can now access this memory area in two ways: π» and π₯.
Now, let’s assume that the developer forgot he freed the space and using the first pointer π» again. He would expect to get “start”, since that’s what we put there, when in reality he’d get “cease”, since the new pointer has already changed the value at this location. Use-after-free vulnerability doesn’t necessarily require overwriting values. One could instead read the data they were not supposed to read.
Pseudocode
class π» UserSunflowerData{
char seeds[100];
public void bloom(){
# some code
}
}
class π₯ UserRoseData{
char petals[100];
public void loose_petals(){
# some code
}
}
int main() {
π» sunflower = new π» UserSunflowerData();
π» sunflower->bloom();
free(π» sunflower)
π₯ username = new π₯ UserRoseData(input("What's your username, pal?"));
π» sunflower->bloom(); // expected to run bloom, but might run π₯ UserRoseData->loose_petals() instead if the same memory location was reused.
}
Now, imagine that the attacker has control over the π₯ username
. For example, they are prompted to enter their desired username. Now, imagine that data is physically located exactly in the same place where the π»sunflower
used to be. One would expect to see the π» sunflower->bloom, but will instead see π₯ rose->loose_petals
.
Examples
Microsoft Explorer had this vulnerability long time ago.