lovekurdt / google-security-research

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

Flash: No Checks on Vector.<uint> Capacity Field #504

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The latest version of the Vector.<primitive> length check in Flash 18,0,0,232 
is not robust against memory corruptions such as heap overflows. While it’s 
no longer possible to obviously bypass the length check there’s still 
unguarded data in the object which could be corrupted to serve as a useful 
primitive. 

To better describe this currently the Vector primitive object (at least on 32 
bit) looks something like:

| unguarded length | unguarded capacity | xored length | ... | data   |

The problem arises because the capacity is not guarded by the xor, and it’s 
before the xored length which is guarded. As we know the unguarded length value 
then if we have a suitable memory corruption vulnerability we could corrupt 
only the length and the capacity fields leaving the xored length alone. Of 
course we’d need to corrupt the length back to the same value (otherwise the 
length guard check would fail). If we set the capacity to be greater than that 
originally allocated then when a call is made to set the length (using the 
length Vector property) the runtime will assume the allocation is larger than 
it is and extend the vector over the end of the original allocation.

This in itself is not enough to serve as a useful primitive as extending the 
vector also 0’s any data afterwards so it’s not an information leak. 
However we’ve now got a vector which aliases some other part of the heap. If 
for example something else was allocated immediately after the vector which we 
can influence then it’d be possible to write data to that and read it out 
from the vector, and vice versa. Also depending on the heap type it might be 
possible to reconstruct heap headers, but it probably isn’t on Windows. As 
vector objects are now on the system heap it’s a lot harder to exploit. 
It’s likely that an attacker would need to utilize browser specific heap 
allocations rather than another flash allocation. 

One way of fixing this, at least against buffer overflows, would be to move the 
xored length before the capacity. In this case the act of overflowing the 
capacity value would corrupt the guard length leading to the check failure when 
setting the new length to exceed the existing capacity. This wouldn’t do 
anything against a heap relative overwrite or a buffer underflow. In that case 
you could also apply the guard to the capacity field as well. If Vectors are 
completely moved out from the heap with other objects, as planned, exploiting 
this would probably be very difficult. 

On a related note, it’s still possible to read the length of the vector 
without triggering the guard check. The length is whatever the unguarded length 
is set to. This could be used as a way of checking which vector objects have 
been corrupted by an overflow. 

I’ve provided a simple example which allocates a 16k UInt vector. Using a 
debugger you can modify the capacity then press a key to show that the process 
doesn’t crash (at least doesn’t crash due to a length corruption). The 
following instructions are for IE11 with 32 bit tabs (the default even on x64 
builds). 

1. Load the swf file into IE
2. Attach WinDBG to the IE tab process
3. Search for the data pattern to find the vector using the command “s 0 
L?10000000 78 56 34 12 f0 de bc 9a 00 00 00 00”. There should only be one hit.
4. Modify the capacity using the command “ed <address>-0xC 5000” replacing 
<address> with that found in step 3. Also look at <address>+0n64*0n1024 which 
will should show other data on the heap. 
5. Resume execution in the debugger.
6. Select the flash object in the browser and press the ‘=’ key, you should 
see a trace message printing the new length.
7. If you return to the debugger and dump the data at <addresss>+0n64*0n1024 
you’ll find the memory has been zeroed. Also at <addresss>+0n64*0n1024+3C you 
should find that the value 0x88888888 has been written to existing allocated 
memory. 

The source is a HAXE file, you need to compile with the command line “haxe 
-main Test -swf output.swf -swf-version 10”

Original issue reported on code.google.com by fors...@google.com on 14 Aug 2015 at 9:02

Attachments:

GoogleCodeExporter commented 8 years ago
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 comment by fors...@google.com on 14 Aug 2015 at 11:06

GoogleCodeExporter commented 8 years ago

Original comment by fors...@google.com on 17 Aug 2015 at 11:11

GoogleCodeExporter commented 8 years ago

Original comment by fors...@google.com on 18 Sep 2015 at 10:45

GoogleCodeExporter commented 8 years ago
Fixed in APSB15-23

Original comment by haw...@google.com on 21 Sep 2015 at 7:44

GoogleCodeExporter commented 8 years ago
Removed view restriction.

Original comment by fors...@google.com on 28 Sep 2015 at 10:15