Monday, April 13, 2015

A Tale of Two Exploits

Posted by Natalie Silvanovich, Collision Investigator and (Object) Field Examiner

CVE-2015-0336 is a type confusion vulnerability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AS2 NetConnection class. I reported this issue in January and soon wrote a proof-of-concept exploit for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug. The issue was patched by Adobe in March and less than a week later, in what was likely a case of bug collision, it was found in two exploit kits in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wild. This created an interesting opportunity to compare a real exploit to a cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365oretical one and better understand how attackers exploit Flash vulnerabilities.


The Bug

CVE-2105-0336 is caused by a faulty check in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ActionScript 2 NetConnection class. To understand cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug, it is important to understand cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure of AS2 objects.

ActionScript 2 is a legacy scripting language supported by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Adobe Flash player. While it shares some classes with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more modern ActionScript 3, it is a unique scripting language with different opcodes and typing rules, implemented in a separate VM. SWF files cannot combine AS2 and AS3 code, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y must eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r be built for an early version of Flash and only use AS2 or be built for a more recent version and only use AS3.

The diagram below shows an AS2 object:

WARNING: This is a dramatization. Code is pseudocode that represents member widths but not exact types. Your AS2 object may be slightly different than pictured. 

AS2 objects are backed by a number of native structures. Typically, an AS2 object is referenced by a pointer-width structure called a ScriptAtom, which contains a pointer (or ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r data for primitives that are not objects). The pointer points to a native ScriptObject that is common to all AS2 classes, and that object contains a several properties (with some indirection), including cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native data and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object. Like an atom, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native data can contain object data (for example, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of a boolean object) or a pointer to a native class that backs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific object type. The interpretation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native data is based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type property of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ScriptObject. The diagram above shows a NetConnection object, where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native data is a pointer to a native NetConnection object.

When a native function uses an AS2 object, it must do a type check before it uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native data. For example, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Number class checks that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ScriptObject is of type Number before casting its native data to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native Number type. CVE-2015-0336 occurs because this check in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection class is faulty. The check passes if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 this object is of type NetConnection, or if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is of type Object and has a NetConnection object in its __proto__ chain (i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is a NetConnection, or a subclass of NetConnection, or a subsubclass of NetConnection and so on). Since objects of type Object should have a null native data property, this check should work. Except cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s one way to get an object of type Object with a non-null native data.

Native functions cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves are represented by an object of type Object in AS2. These objects can be created by calling:


    ASnative(x, y);

The x parameter determines what native function to call, and generally corresponds to a class, such as Number or NetConnection, and is stored as a property in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ScriptObject. The y parameter is used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native function, generally in a switch statement to furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r direct cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call, and is stored as a Number (int for 32-bit build, double for 64-bit build) cast to a DWORD in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object’s native data. This means that if a NetConnection method is called with a parameter that is a native function object, its native data can be specified as a Number by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller, but be interpreted as a pointer (unfortunately only a 32-bit one due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DWORD casting). My proof-of-concept of this issue when I reported it was as follows:

   var b = ASnative(2100, 0x77777777);
   var n = new NetConnection();
   b.__proto__ = n;
   var f = ASnative(2100, 0); //NetConnection.connect
   f.call(b, 1);


b is a native function object with a y parameter and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore a native data of 0x77777777. It has its __proto__ set to NetConnection n so it passes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection class’s type check. When NetConnection.connect is called, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function attempts to access address 0x77777777, which it thinks is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection object and crashes.


Exploiting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Bug

Compared to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r Flash type confusion bugs reported recently, I would characterize CVE-2015-0336 as medium quality. It’s not obviously reliably exploitable on all platforms, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no doubt it can be exploited in some situations. I wrote a proof of concept for Firefox on 32-bit Linux, as this seemed like an environment cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug was likely to work reasonably reliably. In addition, I exploited cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug using AS2 only. This was for two reasons. First, bridging from AS2 to AS3 in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 absence of existing code is time consuming and error prone. Second, I was some concerned that since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection class, exploitation would interfere with AS2/AS3 communication, as all connections are in a global linked list in Flash.

Based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug, I thought cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were a few steps that would be needed to exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug:

  • Create a ‘fake’ NetConnection in memory that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 confused NetConnection pointer points to 
  • Use this object to perform reads to bypass ASLR 
  • Use this object to move IP to ROP gadget addresses found by reading 

To start making a ‘fake’ NetConnection, we need to be able to control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of a buffer at a known location, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection pointer at that location. The lack of contiguous, mutable data types in AS2 makes this difficult. While AS3 contains cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ByteArray and Vector classes which can be used to allocate memory on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap with arbitrary size and contents, AS2 lacks such types. There are a few classes that are close runners up, though. String objects are allocated in contiguous memory and can be of any size, but are not mutable, and terminate as soon as two zero bytes occur. BitmapData objects can be up to 31 MB (81918191), are allocated contiguously and are mutable, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir memory can only be set to valid ARGB pixel values (more details later). A few classes also have members that are backed by heap allocated arrays in memory: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ConvolutionFilter matrix property, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AsBroadcaster _listeners property and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filters property of all objects that support filters. These properties are immutable though, and are limited to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values permitted by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array contents.

I decided to use a BitmapData object, as I noticed that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y have an interesting property. The native data of a BitmapData object is a pointer to a native BitmapData object, which contains many members including a pointer to a pixel buffer. How this buffer is allocated is highly platform dependent, and also varies based on whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device has a GPU on some platforms. I wrote this exploit for Firefox on 32-bit Ubuntu, in which case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pixel buffer is a GDK buffer. This means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pixels are allocated using g_malloc, which uses mmap to allocate larger buffer sizes. Allocating 256 1 MB (2880x91) pixel BitmapData objects, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 objects are consistently 1 MB aligned, and if enough are allocated, it’s fairly easy to guess a location that is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning of one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se buffers, though you don’t know which one. You can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type-confused NetConnection to this address, and create a fake NetConnection object that is backed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BitmapData pixels.

From here, it is pretty easy to control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 instruction pointer, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection object starts with a vtable and NetConnection.addHeader calls an object method immediately-- so long as you’re happy with it pointing somewhere ARGB valid.

ARGB is a scheme for specifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 color of transparent pixels. The A is for alpha and is a one byte value that represents how transparent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bitmap is (255 means it’s opaque and 0 means it’s transparent). The RGB represents standard one byte values containing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intensity of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 colours red, green and blue. Any value is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365oretically ARGB valid, but when Flash stores pixel values, it corrects for transparency. So if a pixel is set to 0xbbff0000 (alpha=0xbb, red=0xff), Flash calculates:

   red = red * alpha / 255

And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 red value is stored as 0xbb (alpha is never altered). So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 subsequent bytes in each four-byte pixel can never be larger than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSB. It is possible to specify an arbitrary four-byte value if it’s not aligned (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 alpha of one pixel is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 LSB, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RGB of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next pixel, with an alpha of 0xff are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remaining bytes), but it is not possible to specify two arbitrary four-byte values in a row, nor any arbitrary aligned values.

Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 instruction pointer does not need to be aligned, it is easy enough to move it to an arbitrary location by making a fake vtable in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BitmapData object that points to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desired IP location. But where to point it?

There are a few methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection object that can be used as info leaks. I started by trying to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nearNonce getter, but this method checks that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection is connected with certain properties before leaking memory, so it is only useful for reading memory locations where a value roughly 200 bytes above cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value is a valid pointer that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method can read. Instead, I used cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nearID getter. This method returns a string at an address that can be specified in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BitmapData buffer, so long as a few ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r values in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer are set so that connectivity checks succeed. The problem with this info leak is that it treats cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory it reads as UTF-8 values when it creates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string it returns. This means that if a character it reads is not a valid UTF-8 value it ignores it and goes to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next value, if it is an unknown glyph, it appends 0xfffd to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string and if it is a valid character it is converted to its UTF-16 equivalent. Practically, this means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 info leak can only reliably return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value at an address if it is an ASCII string.

Even worse, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 info leak reads needs to be aligned, meaning that it can only read locations with addresses that are valid ARGB pixels and point to valid ASCII strings. For a library at a higher address, say around 0xb0000000, that means only about 70% of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address space is addressable, and this goes down for lower addresses. But probabilistically speaking, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s usually going to be something like that every time you load libc, right?

Running strings on libc, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are about 200 strings that are at least 15 characters long and appear only once in libc and no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r library. Creating a table of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir corresponding offsets from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base of libc, and using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 info leak to look for ASCII strings that match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se, it’s possible to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of libc fairly reliably, though sometimes it takes a long time to run. There’s a bit of a tradeoff here. The lower cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address you start with, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more likely you are to find libc, but it takes longer, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 browser eventually prompts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to stop execution. If you start with a higher address it runs faster (most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 good strings are near cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library), but it’s more likely to not find libc and crash when it hits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end mapped memory.

With cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of libc, it’s easy to point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 instruction pointer to a ROP gadget and use it to call system. I picked one that allows both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to system and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to its parameter to be unaligned so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y don’t have to be ARBG valid. The contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string do have to be ARBG valid though, which is why my exploit spawns ghex, which ends with a letter with higher ASCII value than all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs. With a clever use of spacing, it should be possible to run a reasonable set of commands though, and worst case, you could put cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command in a string on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap, and use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 info leak again to search for it.

This exploit works, but suffers from a few problems:

  • It’s not 100% reliable. While it works fairly consistently, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two chances for a pointer to “miss”: when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BitmapData objects are allocated, and when setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to scan for libc.
  • It’s limited to 32-bit platforms. I think this would work on 32-bit Windows with a few changes (in particular, scanning libc for wouldn’t work, but you could probably scan cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap for a relevant value instead), but it definitely wouldn’t work on 64-bit, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 controllable portion of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native data pointer is only 32 bits.
  • The swf is bulky and takes a long time to run.

The Exploit Kits

CVE-2015-0336 was patched by Adobe on March 12, 2015 and an exploit for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug was discovered in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Nuclear Exploit Kit by March 19. A day later, identical exploit code turned up in anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r exploit kit, Angler, and a few ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r exploit kits added cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code later on (you can see more details here). The exploit initially surfaced less than a week after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug was fixed, and before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 details of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug were made public in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Project Zero tracker, meaning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two likely ways cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 authors of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kit could have gained knowledge of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug. The first is through reverse engineering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch, which is possible, but seems unlikely for this specific bug in this time frame. The second, more likely option is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kit authors had previously discovered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue.

This bug was fixed by updating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “normal check”, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function that is used to verify that an object is of type Object. The check was updated to verify that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native function pointer of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is null, meaning that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is not a native function. The fix affected all calls to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check, not just cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection class. Moreover, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 March 12 update added several more normal checks to address CVE-2015-0334. So, in order to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue via reverse engineering, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 authors would have had to realize that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 change in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 normal check function was not related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 additional calls to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function that were added in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch. They would have also had to identify NetConnection as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class containing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch intended to fix, even though this class was not modified in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch, and even though many ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r classes contain similar checks. In addition, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method for creating an object that violates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 condition of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check (calling ASnative to create a native function object and setting its __proto__ to a new NetConnection) isn’t particularly intuitive, and would take substantial time to figure out.

What seems more likely is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit authors already had knowledge of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own independent research, and it being patched caused cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m caused cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to alter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir deployment strategy to include exploit kits. In this case, patching cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug likely prevented a lot of attacks.

Decompiling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sample swf, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit uses both AS2 and AS3, and AS2 is limited to a single class:

   var _loc2_ = _global.ASnative(2100,438181888);
   var _loc3_ = new Object();
   _loc2_.__proto__ = _loc3_;
   _global.ASnative(2100,200)(_loc3_); //Netconnection constructor
   _global.ASnative(2100,8).apply(_loc2_,[1]); //NetConnection.farID


While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 order of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calls is slightly different, this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same type confusion bug, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y used a different NetConnection method to exploit it. My exploit called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nearID getter to read, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call method to set IP, but this exploit only calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 farID getter, which has an identical native implementation to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nearID getter. So how did cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y manage to perform an exploit with only one call?

It turns out that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 near/farID getters set an internal property of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetConnection to a pointer to a string before returning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value. So calling near/farID on a type-confused pointer will cause a value near that pointer to be overwritten with a large value, most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time. There are a few broad things that need to be true about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 surrounding memory, such as certain values not being zero that need to be true for this to work, though.

This is sufficient to use a common exploitation method involving corrupting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of a vector. I won’t go into a lot of detail about this, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is already a great blog entry describing it. The basic idea is that a large number of Vectors are allocated on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory corruption is used to increase cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of one Vector, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n used to increase cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r even furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r to 0x7fffffff, which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n makes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire memory space readable and writable to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker. They cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n read an object value stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Vector to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of a library to bypass ASLR, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable of a different object (which happens to be a FileReference in this case) to set IP.

This exploit is more compact and runs faster than my exploit. Though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no good way to test this, I suspect it is more reliable as well, though it is still reported to suffer from reliability problems. There are likely four sources of unreliability in this exploit:

  • The type confused pointer might not ‘hit’ cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap spray because of unexpected heap entropy.
  • The exploit relies on every 80th vector being different and containing structures for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next stage of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit, which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 author called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lucky Vector. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory corruption hits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 (un)lucky Vector, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit does not work. This happens one in every eighty times.
  • Calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 farID getter might not succeed because a value on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap is not correct.
  • There could be a crash during AS2 to AS3 communication due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection chain containing an invalid NetConnection. This is fairly unlikely to happen, it would require Flash to idle during exploitation. 

My exploit is probably similarly likely to ‘hit’ allocated memory as this one, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y both suffer similar unreliability from this source. Scanning through libc also adds a lot of unreliability to my exploit, and I suspect this greatly outweighs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r sources of unreliability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kit, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y all seem fairly unlikely to happen.

The exploit kit is for 32-bit Windows only, but I suspect this is related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attackers’ motives versus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m not being able to get it to work on Linux. There’s no reason this wouldn’t work on 32-bit Linux if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointers were updated to have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct values.


Conclusion

Unsurprisingly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kits, which were intended for malicious use on a broad scale contained a more reliable method of exploiting CVE-2015-0336 than my proof-of-concept. It’s especially interesting how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y used cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug to corrupt memory when it could also be used to read memory and set IP, which counterintuitively led to a more reliable exploit. While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are a lot of sources of unreliability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kit, it’s likely only two major ones that cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of failures. Avoiding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actions that are most likely to cause failure is what makes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kit more reliable.

Bug collision is one way that Project Zero measures its success because collision disrupts vulnerabilities that are used by sophisticated attackers. Due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 speed at which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit kits released an exploit for CVE-2015-0336 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 difficulty of determining this bug through reverse engineering, we believe it was a case of bug collision. In this case, fixing this bug likely prevented its continued zero-day use by attackers.

1 comment:

  1. Since this is a security blog, could it be updated to not redirect HTTPS to HTTP?

    ReplyDelete