For those paying attention to infosec news, it’s no secret that HackingTeam – a provider of exploits and malware to governments around the world – has been hacked. The hackers who hacked the hackers released a torrent with over 400GB of internal HackingTeam software, tools, write-ups, and, of course, 0-day exploits. One of the exploits we’ve come across was first exposed by the Twitter user @w3bd3vil, and is reminiscent of the “ActionScript-Spray” attack used in CVE-2014-0322 and first documented by Bromium researcher Vadim Kotov. In summary, CVE-2014-0322 used a UAF (user after free) vulnerability in Microsoft’s Internet Explorer to increase the size of an ActionScript Vector object, giving the attacker access to the heap of the process. HackingTeam’s exploit uses this idea to achieve execution, but uses a UAF bug internal to the ActionScript 3 engine.
Note: before diving in, let’s remember that this is not a weaponized 0day, but a PoC that HackingTeam provided to customers, so we don’t have any malicious payload to accompany it; only a simple calc.exe pop.
The UAF vulnerability is quite simple. First, it sprays the heap with multiple ByteArray objects and surrounds each one with MyClass2 objects.
This loop iterates 30 times, effectively filling up the Array object a like so:
for i 1 to 30:
a.insert (ByteArray with length 0xfa0 [4000 bytes])
a.insert (MyClass2 instance)
This spray strategically allocates a chunk of two sequential pages next to each ByteArray object, setting up ActionScript’s memory manager for exploitation. Before I dive into the code that does the exploitation, I want to give you a 10,000 foot view of how the exploit works. When a class instance is placed inside of a ByteArray, ActionScript will attempt to call the class’ member function .valueOf(), which is expected to return the actual byte to insert into the ByteArray; this is where the magic happens. ActionScript internally stores the location to the target ByteArray slot before calling .valueOf(), and it places the returned value at the stored location. In order to exploit this behavior, the attack resizes the target ByteArray from inside of .valueOf(). This causes a new chunk of memory to be allocated for the ByteArray object, freeing the old memory. Before returning, .valueOf() allocates a Vector that matches the size of the old ByteArray object. With a bit of luck (hence the 30 tries), the memory manager places the new Vector object on the freed memory from the old ByteArray. Then, when .valueOf() returns, ActionScript will write the return value directly to the length field of new Vector.
The attack iterates backwards over the sprayed ByteArray objects in a, and attempts to trigger the UAF on each one using this method. Here’s what the implementation looks like:
After .valueOf() returns and the ByteArray is updated, the attack loops over the list of Vector objects that it allocated (stored in _va) and checks their size. If any Vector has a size that is not 0x3f0, it means that the exploit succeeded in partially over-writing the size with the byte 0x40.
From there, the attack uses the same method that was used to write the payload in CVE-2014-0322. The attack treats the affected Vector as a pointer to the entire memory space of the program (well, not the entire memory, but all memory following the Vector). It uses this to scan memory for the PE header of KERNEL32.DLL and grabs the address of VirtualProtect from the export table. Next, it overwrites the VFT (virtual function table) of an internal class with the address of VirtualProtect, and calls the function to set the memory of the MyClass2 instance directly after the affected Vector to PAGE_EXECUTE_READWRITE. With the MyClass2 memory set to executable, the attack finishes by finally placing its shellcode payload within the MyClass2 instance and using the same VFT trick to execute it.
Out of the box, this exploit comes with shellcode for Windows (both 32 and 64 bit) and Mac OSX (64 bit only). According to the documentation present in the dump, this exploit should work with every version of Flash Player from version 9 until 188.8.131.52. We’ve got it working internally with Flash Player 18 and Internet Explorer, which indicates this it is clearly a zero day risk to internet users today. Given legitimately sophisticated shellcode and mitigation bypass techniques similar to the ones documented by Bromium researcher Jared DeMott, this exploit has the potential to completely own almost any system that it hits, and can be reliably blocked by leveraging robust isolation technologies.
UPDATE 7/8/2015: It seems like Adobe has already released a patch for this vulnerability, and Flash Player versions 184.108.40.206 and above should be protected.