Monday, August 17, 2015

Attacking ECMAScript Engines with Redefinition

Posted by Natalie Silvanovich = function () { return n; }

ECMAScript has a property where almost all functions and variables can be dynamically redefined. This can lead to vulnerabilities in situations where native code assumes a function or variable behaves a certain way when accessed or does not have certain side effects when it can in fact be redefined. Project Zero has discovered 24 vulnerabilities involving ECMAScript redefinition in Adobe Flash in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 past few months and similar issues have also been discovered in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wild. This post describes how this class of bugs works, alongside some examples of interesting bugs that have been recently patched.

ECMAScript Redefinition


Being a dynamically typed language, ECMAScript allows all functions to be redefined. For example, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JavaScript below redefines cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 alert method.


In most browsers, this will cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function document.write to be called instead of a native alert.

While this example is fairly benign, in some situations this behaviour can be problematic and lead to bugs. In particular, if native code in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VM relies on an ECMAScript method having specific behavior, but it has been redefined, it can lead to many issues, especially type confusion, overflows and use-after-frees.

Past Redefinition Bugs


Many security bugs involving redefinition have been discovered in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 past. Some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 earliest bugs were bypasses of same-origin-policy in browsers, where redefining a JavaScript function could allow script from an insecure context to be executed. Issues of this type have been found as recently as last year.

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 past couple of years, many memory corruption and use-after-free bugs of this type have been found in browsers, such as CVE-2013-0765 in Firefox and  CVE-2014-1705 in Chrome.

The recent HackingTeam leak contained five Adobe Flash vulnerabilities, of which four involved redefinition (CVE-2015-5119, CVE-2015-5122, CVE-2015-5123 and CVE-2015-0349).  An analysis of CVE-2015-5119 is included below

How to Redefine an Object

One of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main challenges in finding and exploiting redefinition vulnerabilities is reachability. Many of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues exist deep in code, and it is not always obvious how to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.  Moreover, not all ECMA-based languages support redefinition to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same degree, and it often varies based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific function and method being redefined. That said, ECMAScript supports many methods of gaining access to objects, so it is often possible to reach redefinition using less-used ECMAScript functionality.

Equality Operator


The equality operator is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 simplest way to redefine an object or function and it works to some extent in most ECMAScript implementations. In ActionScript 2, it works without restriction so long as a field doesn’t have a setter defined (although sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code doesn’t compile and needs to be written directly in bytecode). Even read-only properties in AS2 can be redefined with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 equality operator by calling ASSetProps to remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 read-only flag first. In ActionScript 3, only classes that are declared as dynamic can have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir methods redefined using equality. In browsers, most methods can be redefined using equality, although one host function cannot be set to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r host function directly. For example, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning of this post, alert can be set to document.write, but it needs to wrapped in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function f first. Direct assignment will cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 script to fail to execute.

CVE-2015-3077


CVE-2015-3077 is an example of a vulnerability in Flash that occurs because a function can be redefined using equality. A sample of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code that causes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue is below. Note that this code has been simplified for clarity, and does not compile. A compiling sample of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code can be found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Project Zero bug tracker.   

var blur = new flash.filters.BlurFilter(100, 15, 5555);
this.filters = [blur]; //this is a Button
flash.filters.BlurFilter = flash.filters.ConvolutionFilter;
var f = this.filters;
var conv = f[0];
conv.matrix = [0,1,1,1,1,1,1,1,1,1,1,1,1,1];

This is a simple type confusion issue. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Button.filters method is set, it creates a native array containing all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filters and stores it. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Button.filters property is read, it creates ActionScript objects of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of each filter by calling its ActionScript constructor (with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 assumption it hasn’t been redefined) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n setting its native backing object to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor for a filter is redefined, it calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wrong filter type, but still sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same native object. This leads to an AS object of one type being backed by a native object of anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r type, leading to type confusion.

CVE-2015-0305


CVE-2015-0305 is anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r example of a type confusion issue that occurs through redefinition via equality.

var b = flash.net;
b.FileReference = q;
function q(){
 this.f = flash.display.BitmapData
 var c = new this.f(1000, 1000, true, 1000)
}
var file = new FileReferenceList();
file.browse();

It is fairly similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous case. When FileReferenceList.browse is called, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 browser spawns a dialog and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user selects files. Then, for each file, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 browse method calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FileReference constructor and creates an object for each file. In this bug, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor is overwritten with a constructor that initializes it as a BitmapData object. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor is called, its type is set to FileReference, even though it is not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type that is returned. This leads to an object with an AS object type and native object type that are inconsistent, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore type confusion. The bug is that FileReferenceList.browse assumes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FileReference constructor will return a FileReference, even though this isn’t guaranteed because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method can be redefined.

Proxy Objects


Proxy objects can be used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 place of regular objects. They allow functions that handle every property access and method call to be defined. They can sometimes be used to redefine a property where equality fails. They also have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 benefit of being able to execute code every time a property is accessed, which can allow behaviour which isn’t possibly when simply setting a property, such as returning a different value each time a property is accessed. ActionScript 3 and JavaScript support Proxy objects.

CVE-2015-0327


CVE-2015-0327 is an issue found by Ian Beer that can be triggered by calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stringify method in AS3 on a Proxy object.

while (index != 0) {
 ownDynPropCount++;
 index = value->nextNameIndex(index);
}

AutoDestructingAtomArray propNames(m_fixedmalloc, ownDynPropCount);
while (index != 0) {
 Atom name = value->nextName(index);
 propNames.m_atoms[propNamesIdx] = name;
 propNamesIdx++;
 index = value->nextNameIndex(index);
}

The code above is from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open-source AVM. It counts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 elements in value, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length to allocate an array. The array is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n set by enumerating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 items in value. However, if value is a Proxy object, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of elements in each enumeration is not necessarily consistent, which can lead to an overflow in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated buffer.

Conversion Operators


Conversion operators, such as toString, valueOf and toInt can often be called implicitly. For example, when calling a native method such as:

var b = new BitmapData(x, y, true, 0xff00ff);

This will usually call valueOf on x and y to convert cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to integers if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are not already. Functions that take string input often display similar behavior with toString. This can be an avenue for executing scripts at unexpected times. Conversion operators can be redefined in both AS2 and AS3.

CVE-2015-3039


CVE-2015-3039 is a bug in AS2 where calls to conversion operator allows script to be executed unexpectedly during a native call.

var filter = new ConvolutionFilter(...);
var n = {};
n.valueOf = ts;
var a = [];
for(var k = 0; k < 1; k++){
a[k] = n;
}
filter.matrix = a;
function ts(){
filter.matrix = a;
}

When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native matrix getter is called, it first deletes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing matrix, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n reallocates a new one and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n sets its contents to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 provided matrix. When it fetches cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 matrix, it calls valueOf to convert cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array to members of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Number class. However, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 valueOf function also calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 matrix getter, it will delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 matrix array, and reallocate it, even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous call isn’t complete, and will write to it after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second call returns. This leads to a use-after-free bug.

CVE-2015-5119

CVE-2015-5119 is a bug discovered in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HackingTeam leaks which occurs because calls to a conversion operator can cause a buffer to be freed and reallocated before a write to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original buffer.

var b = new ByteArray();
b.length = 12;
var n = new myba(b);
b[0] = n;

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 myba class definition:

prototype.valueOf = function()
{
b.length = 1000;
}

This bug is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AS3 interpreter unlike cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AS2 interpreter for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue above, so valueOf has to be redefined in a class definition as shown. The vulnerable code is part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open source AVM, and is as follows:

void ByteArrayObject::setUintProperty(uint32_t i, Atom value)
{
m_byteArray[i] = uint8_t(AvmCore::integer(value));
}

The AvmCore::integer method calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 valueOf method defined for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object value, which corresponds to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 variable n in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ActionScript above. This 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 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 byte array, which can cause it to be reallocated. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write occurs on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original buffer, leading to a use-after-free.

Watches


Watches are anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r method that can be used to change a property of an object. They are supported generically in AS2 and JavaScript. Watches trigger whenever an object property without a custom setter is set. This can sometimes mean that when a native method sets a property, a watch will trigger, allowing a jump into script, and also cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability to change what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 property is set to, as a watcher can return a value which supersedes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller is trying to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 watched field to.

CVE-2015-3120


CVE-2015-3120 is a type confusion issue that can be reached by setting a watch on a variable.

var fileRef:FileReferenceList = new FileReferenceList();
fileRef.addListener(listener);
fileRef["fileList"] = "asdf";
fileRef.watch("fileList", func);
fileRef.browse(allTypes);

function func(){
return 7777777;
}

Setting a watch on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 variable fileList causes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function func to be triggered when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native browse function creates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fileList object and attempts to set it. The function cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n returns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value 7777777, which is a Number, replacing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object that is set. This leads to type confusion when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 variable is used, assumed to be an ActionScript object and used as a pointer as opposed to a Number.

CVE-2015-3119


CVE-2015-3119 is a bug in AS2 that can be triggered by setting a watch on a variable:

class mysubclass extends NetConnection {
function mysubclass(a){
this.uri = "test";
super();
this.watch("uri", func);
var n = {toString : func}
var s = super;
trace(y);
this.connect(y);
var f = ASnative(2101, 411); //setBufferTimeMax
f.call(this, 1000);
function func(a, b, c){
var f = ASnative(2101, 200); // newStream
var n = new NetConnection();
n.connect(y);
f(this, n);
}
}
}

A watch is set on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 URL property of a NetConnection object, and when it attempts to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 URL, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function func is called. This function redefines cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 this object as a NetStream (as opposed to a NetConnection), which leads to type confusion. The watch makes this possible, as it occurs after type checking, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function would fail to execute if called as a NetStream.

Subclassing


Sometimes it is possible to redefine a method or property of a class by subclassing it, if you control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 construction of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object. Classes in ActionScript and JavaScript can be subclassed using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 extends keyword. In addition, classes can sometimes be dynamically extended using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 __proto__ or prototype keyword.

Resolution Methods


JavaScript and AS2 objects also support resolution methods. These are methods are called when resolution of a property or method fails, as a last resort.  In ActionScript 2, __resolve is a resolution function that gets called if resolution of a property or method fails. In JavaScript, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are a series of __lookUp*__ methods, such as __lookUpGetter__ which serve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same purpose (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific method that get calls depends exactly on what type of resolution fails). These functions can be used to redefine methods or properties to reach bugs, but are also useful in finding bugs. Calling a native method on an object with a resolution method set is a good way to figure out what properties of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method is accessing, which can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be modified furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r

Conclusion

Redefining host methods and properties can often violate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 assumptions made by ECMAScript VMs when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. This is a good avenue for finding bugs in this type of software.

No comments:

Post a Comment