Video Screencast Help
Symantec to Separate Into Two Focused, Industry-Leading Technology Companies. Learn more.
Security Response

Double Free Vulnerabilities - Part 2

Created: 22 Jan 2007 08:00:00 GMT • Updated: 23 Jan 2014 18:53:20 GMT
Matthew Conover's picture
0 0 Votes
Login to vote

Continued from Part 1...

Exploiting double free vulnerabilities: Case 1

The first way that a double free vulnerability can be exploited is when the first free puts the chunk on the Lookaside (which the Windows heap implementation tries to use before the FreeList since it's more efficient). When a chunk is freed to the Lookaside, the Chunk is still marked as busy (that is, Chunk.Flags & BUSY_FLAG is set) to prevent the chunk from being coalesced with the previous/next chunk. That's because entries on the Lookasidelist are meant to be a fast allocate/deallocate (akin to "fast bins" inthe GLIBC and related Unix heap implementations). By contrast, entrieson the FreeList are frequentlycoalesced when a chunk is being freed and the chunk before/after it isalso free (to make larger contiguous chunks of memory available andavoid heap fragmentation).

So after the first free (in the double free vulnerability) the chunk is put onto the Lookaside and left marked as busy. The Lookasidewill only fit four entries per chunk size (initially)—in other words,only allow four chunks of size X before putting the remainder on the FreeList.If an attacker can manipulate how many allocations/frees occur (as ispossible with some vulnerabilities, such as the Exchange XEXCH heapvulnerability from a year or two ago), the attacker can cause the firstfree to fill up the Lookaside. The second free (the double free that produces the vulnerability), therefore, will also put the chunk onto the FreeLists. That is, there are two different locations—the Lookaside[SizeX] and also the FreeLists[SizeX]—that point to this chunk. That means we can allocate the chunk off the Lookaside first (since the Lookaside is checked first) and then overwrite the Flink/Blink still contained in the chunk's data (since it's still on the FreeList). So when the SizeX chunk on the FreeLists is eventually allocated, it will unlink that chunk (which is simultaneously allocated via the Lookaside) and a four-byte overwrite will occur since the attacker has already modified that chunk.

Exploiting double free vulnerabilities: Case 2

Another interesting case of double frees is when both times the chunk is put on the Lookaside list (that is, there are at least two available slots on Lookaside[SizeX]). Since the entry is still marked as busy after the first free (since chunks on the Lookaside are left as busy) it will be freed again, and the same chunk will be on the Lookaside twice:

Lookaside[SizeX] -> AttackerChunk -> AttackerChunk

This means that after the first allocation, AttackerChunk will be returned (the first entry) but Lookaside[SizeX] will still point to AttackerChunk. Because AttackerChunk has already been allocated once, the attacker can modify the Flink pointer (offset 0 of a free chunk on the Lookaside) and then allocate a SizeX chunk again. The Lookaside will now point to arbitrary address. With one final allocation of SizeX, the attacker will receive a pointer to whatever address he overwrites the Flink with and will be able to modify up to SizeX bytes at an arbitrary address in memory.

Windows Vista heap mitigations

Heap overflows on Windows Vista have several mitigations that will make double free vulnerabilities more difficult to exploit:

1. Randomized heap base. You need to know the FreeLists[] address in order to defeat safe unlinking.
2. The Flink/Blinkare now encoded pointers (they are XOR’d with a random valueinitialized once when the process starts). So even if you know the FreeLists[] address, you also have to know the random value that the Flink/Blink are XOR’d with. If you guess the incorrect random value, you will read from random memory locations.
3. Exit on heap corruption rather than silently ignored. This is opt-infunctionality, as far as I know, but most of the Windows corecomponents (I assume CSRSS also) will have this enabled.
4. The Lookasidelist has been replaced with the Low Fragmentation Heap (LFH). I’vebriefly touched on the LFH implementation in the SyScan 2004presentation. It has not been well analyzed yet, but initialindications are that LFH is significantly harder to abuse than the Lookaside list was.