VegarLH / google-security-research

Automatically exported from code.google.com/p/google-security-research
0 stars 0 forks source link

Flash: bypass of Vector.<uint> length vs. cookie validation #482

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
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.

Original issue reported on code.google.com by cev...@google.com on 15 Jul 2015 at 1:05

Attachments:

GoogleCodeExporter commented 9 years ago
Actually, for the "How to fix?" suggestion, maybe a better one is:

- Generate a random cookie value once and store it in a static variable. Thanks 
James.

Original comment by cev...@google.com on 15 Jul 2015 at 5:57

GoogleCodeExporter commented 9 years ago

Original comment by cev...@google.com on 15 Jul 2015 at 6:11

GoogleCodeExporter commented 9 years ago

Original comment by natashe...@google.com on 11 Aug 2015 at 3:04

GoogleCodeExporter commented 9 years ago

Original comment by cev...@google.com on 19 Aug 2015 at 8:11

GoogleCodeExporter commented 9 years ago
Related blog post: 
http://googleprojectzero.blogspot.com/2015/08/three-bypasses-and-fix-for-one-of.
html

Original comment by cev...@google.com on 19 Aug 2015 at 8:12