|
|
Flash: bypass of Vector.<uint> length vs. cookie validation | |||
| Reported by cevans@google.com, Jul 15 2015 | Back to list | |||
Flash v18.0.0.209 (https://helpx.adobe.com/security/products/flash-player/apsb15-18.html) contains new mitigations to defend against corruptions of Vector.<uint> (and other) lengths. One of these mitigations, at Vector access time, compares the Vector's in-memory length with a representation of the same length XOR'ed with a secret cookie. The bypass comes about because the secret cookie value is stored inside a structure, and a pointer to that structure is stored alongside the Vector length. Accordingly, the concept of the attack is to corrupt all of these things in the same header at the same time: - The length. - The length XOR'ed with the secret cookie. - The pointer to the secret cookie. At first glance, the attack may not sound too potent because it requires forging a pointer value, which generally requires an ASLR defeat. Given that Vector.<uint> corruptions are the common way to defeat ASLR, this introduces a chicken-and-egg problem for the attacker. However, there are two situations where the attacker can forge a pointer value easily: 1) In 32-bit processes, the attacker can just allocate e.g. a 1GB ByteArray to spray the heap such that a specific address is known; and a repeating pattern can be placed inside the ByteArray so that known content is placed at the known address. 2) The attacker can abuse "User Shared Data", even on 64-bit processes. This is significant because spraying is generally not a good option in 64-bit processes. Taking Win 8.1 x64, all processes have a 1-page read-only mapping at 0x7ffe000, and the content is predicatable enough for our needs. A specific attack against item 2) above on Win 8.1 x64 is presented. I don't have any good heap overflows handy at the moment, so you can "fake" the attack successfully in the debugger. This applies to Chrome Windows, 64-bit: 1) Run the SprayPoll.swf attached SWF. Wait 10 seconds for the first output. 2) Attach WinDbg and locate the mapping tagged "Heap", and sized 0x0`20000000 (512MB). That's a Vector.<uint> buffer. .symfix .reload !address -> locate it. Example addr: 0x8e`80008000 3) Bring up the memory view and locate the Vector.<uint> buffer object: (At 0x8e`80008040): 0x07ffff83 0x07ffff83 0x8b6fd5d7 0x00000000 0x86f53000 0x00003d3c 0xf2f2f2f2 0x00000000 0x07ffff83 is the length, followed by the capacity, followed by length XOR cookie, followed by 32-bit 0x0, followed by a 64-bit pointer, followed by 0xf2f2f2f2 (value put inside the Vector). 3) Simulate a linear heap overflow in the debugger. The challenge as attackers is to pick a sequence of bytes that corrupts this header, without having to know any secrets, and results in a Vector.<uint> object that can access out-of-bounds without trapping at runtime. We pick this sequence: 0x07ffff84 0x07ffff84 0x07ffff84 0x00000000 0x7ffe0000 0x00000000 0xf2f2f2f2 0x00000000 Write that sequence into the memory window and resume the Flash process in the debugger (g). 4) Observe success for the attacker. An out-of-bounds read is demonstrated in the SWF output text. There is no crash. How does it work? By pointing the structure that contains the secret cookie into the User Shared Data mapping, we effectively pick a secret cookie value of 0x0. This occurs because the secret cookie offset within the structure is large (0xc68 or so), and User Shared Data is padded with nul bytes at the upper end. Note that User Shared Data is at a fixed location, which enables the attacker to proceed here without knowing any secrets. Once the secret cookie is set to 0x0, the length XOR cookie value can simply be set to the same value as the desired fake length. And job done. Note that this attack, although generic, will only work for a subset of heap overflows: those where the attacker can write arbitrary bytes out-of-bounds, and at least 24 of them, and including the nul byte. This is reasonably common but not 100% of heap overflows. The defense may also hold against other vulnerability classes, such as use-after-free or type confusion, where the attacker may have less control over the corruption of memory content. How to fix? The cookie should probably not be fetched via a pointer that the attacker can corrupt. Alternative sources of cookies may include: - The address of some function inside a DLL, which may provide enough entropy, particularly on 64-bit builds. - The address of the Vector.<uint> buffer itself. I think this section option may be ok, but please do apply critical thought to the idea in case I haven't had enough caffeine. This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.
Comment 1
by
cevans@google.com,
Jul 15 2015
,
Jul 15 2015
,
Aug 11 2015
,
Aug 19 2015
,
Aug 19 2015
|
||||
| ► Sign in to add a comment | ||||