Understanding type confusion vulnerabilities: CVE-2015-0336


In March 2014, we observed a patched Adobe Flash vulnerability (CVE-2015-0336) being exploited in the wild. Adobe released the patch on March 12, 2014, and exploit code using this vulnerability first appeared about a week later.

To help stay protected:

  • Keep your Microsoft security software, such as Windows Defender for Windows 8.1 up-to-date.
  • Keep your third-party software, such as Adobe Flash Player, up-to-date.
  • Be cautious when browsing potentially malicious or compromised websites.

This blog digs deeper into the technique and tactics the attacker used to exploit this vulnerability. Understanding these techniques can help you better defend your enterprise software security infrastructure against similar exploits.

First things first, let’s talk about the vulnerability itself. The vulnerability is a “type confusion”, a common technique with ActionScript Virtual Machine. Usually, when a piece of code doesn’t verify the type of object that is passed to it, and uses it blindly without type-checking, it leads to type confusion. Type confusion can be very dangerous because a type is expressed as a layout of memory in the lower level implementation of Flash Player. Also with type confusion, wrong function pointers or data are fed into the wrong piece of code. In some circumstances this can lead to code execution.

Figure 1 shows the CVE-2015-0336 exploit code that triggers the vulnerability. This piece of code resembles the proof of concept code detailed by the finder, however, the details are somewhat different.

The first difference is the usage of an ASnative(2100,200) call instead of a NetConnection class initiation. Also, the code that triggers the confusion is different. The exploit utilizes method 8 (line 9) and calls to apply method of NetConnection function object to trigger the type confusion. The original Google Project Zero code used method 1 and a call method on this object.

Type confusion code

Figure 1: Exploit code that triggers type confusion

The object that is passed to ASnative(2100,8) function is the _loc_2 object. The _loc2_ object is an ASnative function object that doesn’t exist. It’s just a placeholder for a function object. However, this ASnative object from line number 5 is very important in the exploitation technique, as discussed below.

The _loc2_ object is not a NetConnection object at all – its __proto__ property is set to an Object type object (_loc3_). ASnative(2100,200) is a constructor for the NetConnection object and this _loc3_ object is initialized to the NetConnection type at line 8. This makes the line 9 code to use the non-NetConnection object as a NetConnection object and treats the object’s memory layout as if it is a NetConnection object. Figure 2 shows the actual code that checks for the __proto__ property. With an updated binary, this part is fixed with more sanity checks to prevent unwanted objects passed down further into the code below.

Proto object check

Figure 2: The proto object check routine

The function that checks code for the proto object is actually a function that processes the ASnative(200,x) commands. It has a jump table that processes each function cases, as shown in Figure 3.

Jump table

Figure 3: Jump table for function dispatch

The function number 8 falls through the jump table to the code piece as shown in Figure 4. If all the payload and vector spray code is removed from the exploit, it will crash.

Crash point

Figure 4: Crash point

The actual crash point looks like this:

7061f9b2 8b4f7c          mov     ecx,dword ptr [edi+7Ch] ds:002b:1a1e207c=????????

It tries to access an invalid memory pointed to by the non-NetConnection object.

At this point, edi designates the start of the object as 0x1a1e2000. This value is directly controlled by the attacker. From the code below, 438181888 is actually 0x1a1e2000. This is an unexpected feature with ASnative and the ActionScript engine. You can control exactly what ASnative (edi) designates here:

var _loc2_ = _global.ASnative(2100,438181888);

The exploit author tried to find and use an instruction that writes a field inside the fake object. First, it sprays a lot of vector objects on the memory. The specific exploit that we analyzed creates more than 120,000 counts of vector.<uint> objects with a length of 0x3FE, as shown in Figure 5. After spraying these objects, it shrinks the size of each vectors to 0x1E to make some empty rooms.

Vector object created

Figure 5: Vector object creation

We know that the fake ASnative object points to 0x1a1e2000 and that this address is allocated by the exploit code with the vector.<uint> object from heap spray code, as shown in Figure 6.

From our testing, the allocation behavior from the ActionScript virtual machine was predictable, and we saw 100% allocation of this memory area. The attacker acquires full control over the contents of the fake NetConnection object. Whatever value it fills for the object from the vector.<uint> array will be recognized as a NetConnection object.

fake NetConnection object

Figure 6: Vector.<uint> with a size of 0x1e is used as a fake NetConnection object

This fake NetConnection object is passed to various functions and treated as a real NetConnection object. The attacker figured out that they can use function 8 to achieve vector corruption. Function 8 has one of the subroutines that passes one of the NetConnection member objects located at the offset of 0x7C, as shown in Figure 6. The object’s variable at offset 0xBD8 is overwritten later by an instruction.

Figure 7 shows the data flow and how a specific memory location can be written with a value from the new function call. The overwritten location is 0x1a1e2001 – right inside the vector.length field. Now the exploit has full control over an excessive amount of memory area. With this extra power, it can perform additional vector corruption to open up full range memory control.

Vector corruption

Figure 7: How vector corruption occurs

After the vector corruption, the exploit builds an ROP chain and shellcode by reading into the process memory and collecting the required gadget locations. The exploitation creates a FileReference object on the memory and overwrites its cancel method to the attacker-controlled code.

After that, it calls the FileReference.cancel method to pass control to malicious code.

Calling FileReference.cancel

Figure 8 Calling FileReference.cancel method

In conclusion, this vulnerability resides in the old ActionScript 2 engine, an area that was ignored by malicious attackers for some time. However, now that a vulnerability in this legacy code has been revealed, we might see more exploited.

When the vulnerability itself is a type confusion, exploiting it is relatively easy for an attacker utilizing old methods of corrupt vector objects. The predictable behavior of vector allocation and layout implementation of Adobe Flash Player has been exploited for some time. Using the vector corruption method, an attacker can gain a reliable entry point to further exploit vulnerabilities that are otherwise not so simple to exploit.

Understanding how this exploit works helps us to be better prepared to detect and patch future exploits. Exploits such as this are usually delivered through exploit kits.

Jeong Wook Oh
MMPC


Comments (7)

  1. Eddy Current says:

    As usual you forgot your 1st line of defense in your "To help stay protected:" enumeration:
    turn on "data execution prevention" in the filesystem!

    See NTFS access rights, SAFER alias software restriction policies or AppLocker for instructions

  2. Graham says:

    Eddy's comment is incorrect. The use of ROP chains in this exploit already bypasses DEP, and ASLR is bypassed also due to the leak of memory revealing the necessary pointers. Filesystem permissions are also irrelevant – I'm not sure what he's talking about
    there.

    If you want a better defense against this kind of thing, Microsoft EMET is a good option. Also, as mentioned at the top of the article, patch!

  3. Dave says:

    Think so dang.It had control of my keyboard functions.

  4. adwbust says:

    there are some old PE (flv) players that are wrapped around/bundled with outdated flashplayer runtime though. aside from swf and mov, can mp4 or flv carry this malicious actionscript code?

  5. mike says:

    eddy is an idiot lol

  6. Alfred E. Neumann says:

    Graham but misses the point Eddy made.
    Cf. http://www.asd.gov.au/infosec/mitigationstrategies.htm:

    "At least 85% of the targeted cyber intrusions that the Australian Signals Directorate (ASD) responds to could be prevented by following the Top 4 mitigation strategies listed in our Strategies to Mitigate Targeted Cyber Intrusions:

    use application whitelisting to help prevent malicious software and unapproved programs from running
    patch applications such as Java, PDF viewers, Flash, web browsers and Microsoft Office
    patch operating system vulnerabilities
    restrict administrative privileges to operating systems and applications based on user duties.

    The Strategies to Mitigate Targeted Cyber Intrusions are ranked in order of overall effectiveness. Rankings are based on ASD’s analysis of reported security incidents and vulnerabilities detected by ASD in testing the security of Australian government networks."

    JFTR: mike is an even bigger fool!

  7. Ian Macdonald says:

    Seems to me this is essentially another buffer overflow exploit, of the kind to which C code is so prone. The fact that it is exploited in a slightly different way doesn’t alter the fact that C’s failure to check data bounds is at the root of the problem.