Thursday, July 24, 2014

pwn4fun Spring 2014 - Safari - Part I

Posted by Ian Beer
Back in March this year I entered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pwn4fun hacking contest at CanSecWest [ http://www.pwn2own.com/2014/03/pwning-lulzand-charity/ ] targeting Safari running on a brand new MacBook Air. In this first post I’ll detail how I got code execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Safari renderer sandbox using a bug in its javascript engine JavaScriptCore. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second part I’ll explain how I broke out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox and into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel to be able to fully compromise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target system.
Bug Hunting
Looking at old bugs is a great way to quickly find new ones. Sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root cause of a bug can be subtler than it appears and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch only fixes a symptom racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug. Sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re can be ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r variants of a bug which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch missed. And sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch just introduces new bugs, especially if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code is complicated.
In this case I chose to target a bug which was incorrectly fixed by [ https://trac.webkit.org/changeset/145594 ] which was fixing [ https://bugs.webkit.org/show_bug.cgi?id=112093 ]. WebKit security bugs are rarely opened up to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 public so we can’t see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original bug report, only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix:

Index: trunk/Source/JavaScriptCore/runtime/JSStringJoiner.h
===================================================================
--- a/trunk/Source/JavaScriptCore/runtime/JSStringJoiner.h
+++ b/trunk/Source/JavaScriptCore/runtime/JSStringJoiner.h
@@ -47,5 +47,5 @@
    Vector m_strings;

-    unsigned m_cumulatedStringsLength;
+    Checked m_accumulatedStringsLength;
    bool m_isValid;
    bool m_is8Bits;


Index: trunk/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
===================================================================
--- a/trunk/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
+++ b/trunk/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
@@ -103,10 +103,14 @@
        return jsEmptyString(exec);

-    size_t separatorLength = m_separator.length();
+    Checked separatorLength = m_separator.length();
    // FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1).
    ASSERT(m_strings.size() > 0);
-    size_t totalSeparactorsLength = separatorLength * (m_strings.size() - 1);
-    size_t outputStringSize = totalSeparactorsLength + m_cumulatedStringsLength;
+    Checked totalSeparactorsLength = separatorLength * (m_strings.size() - 1);
+    Checked outputStringSize = totalSeparactorsLength + m_accumulatedStringsLength;

+    size_t finalSize;
+    if (outputStringSize.safeGet(finalSize) == CheckedState::DidOverflow)
+        return throwOutOfMemoryError(exec);
+        

This patch is trying to fix multiple integer overflow bugs in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner class by replacing raw integer types with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Checked<> template. This template abstracts away cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fiddly details of checking for integer overflow and makes it easier to write safe code. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 safeGet() method returns CheckedState::DidOverflow 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 computed value (outputStringSize) is discarded and a javascript out-of-memory exception will be generated.

Grepping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JavaScriptCore source code we can see that JSStringJoiner is used in three places: arrayProtoFuncToString, arrayProtoFuncToLocaleString and arrayProtoFuncJoin which are all in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file ArrayPrototype.cpp. The function names are quite self-explanatory, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se three functions implement cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 toString, toLocaleString and join methods of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 javascript Array object prototype.

Taking a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MDN documentation for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Array object [ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array ] we can see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se three functions are quite similar. They all return a string representation of an array, just formatted slightly differently:

  • Array.prototype.toString calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 toString() method for each element in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array and connects all those strings togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r with a comma
  • Array.prototype.toLocaleString is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same but calls toLocaleString() for each element instead
  • Array.prototype.join calls toString() for each element and also allows you to specify your own separator string racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than having to use “,

Here’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of arrayProtoFuncJoin, edited to just show cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interactions with JSStringJoiner:

EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
{
 [...]

If an argument to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 javascript function was supplied, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n convert it to a string and assign that to separator. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise create a string containing a comma and assign that to separator:

 String separator;
 if (!exec->argument(0).isUndefined())
   separator = exec->argument(0).toWTFString(exec);
 if (separator.isNull())
   separator = String(",", String::ConstructFromLiteral);

Create a JSStringJoiner on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack, passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 separator string and array length to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor:

 JSStringJoiner stringJoiner(separator, length);

For each element of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array, convert cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 element to a string and pass that string to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 append method of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner:

 [...]
 unsigned k = 0;
 for (; k < length; k++) {
   JSValue element = thisObj->get(exec, k);
   if (!element.isUndefinedOrNull())
     stringJoiner.append(element.toWTFStringInline(exec));
 }

Finally call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 join method of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner to get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting string and return it:

 return JSValue::encode(stringJoiner.join(exec));
}

Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of JSStringJoiner::append it’s clear what one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patched bugs was:

inline void JSStringJoiner::append(const String& str)
{
 [...]
 m_strings.append(str);
 if (!str.isNull()) {
   m_accumulatedStringsLength += str.length();
   m_is8Bits = m_is8Bits && str.is8Bit();
 }
}

Since m_accumulatedStringsLength used to be an unsigned int, by creating an array containing many references to a long string and calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 join method we could have easily overflowed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 m_accumulatedStringsLength variable:

var long_string = “A”;
for (var i = 0; i < 16; i++){
 long_string = long_string + long_string;
}
//long string is now “A”*0x10000
arr = [];
for(var i = 0; i < 0x10001; i++){
 arr.push(long_string)
}
arr.join()

Here we create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string long_string with a length of 0x10000 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n append that same string 0x10001 times to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array arr. Note that this doesn’t create 0x10001 copies of long_string; each element of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array is just a reference to long_string.

When we call join on arr we’ll invoke cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native code seen earlier (arrayProtoFuncJoin) and end up calling JSStringJoiner::append 0x10001 times, each time passing a pointer to long_string. The 0x10000’th time append is called m_accumulatedStringsLength will have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value 0xffff0000, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following line:

   m_accumulatedStringsLength += str.length();

will correspond to performing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following calculation:

   m_accumulatedStringsLength = 0xffff0000 + 0x10000

The result of that addition is 0x100000000 (that number has 8 zeros) or 2^32 which is outside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 range of values representable by an unsigned int. This is an integer overflow, and after executing this line m_accumulatedStringsLength will have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value 0 (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 upper bits outside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 range of a 32-bit value are simply dropped.)

When we append cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final 0x10001’th string m_accumulatedStringsLength will become 0x10000 again. Presumably bad things will now happen. This bug was patched by changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of m_accumulatedStringsLength to Checked so when that 0x10000'th string is appended cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow will be detected and any subsequent safeGet will fail.

LP64


Safari on OS X is a 64-bit process and OS X uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 LP64 type model which means that size_t is a 64-bit type and int and unsigned int are 32-bit types. With this in mind, lets look at that patched code again, specifically cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new overflow checks added in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner::join method:

 Checked separatorLength = m_separator.length();
 Checked totalSeparactorsLength =
     separatorLength * (m_strings.size() - 1);
 Checked outputStringSize =
     totalSeparactorsLength + m_accumulatedStringsLength;

 size_t finalSize;
 if (outputStringSize.safeGet(finalSize) == CheckedState::DidOverflow)
   return throwOutOfMemoryError(exec);

(Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 state stored by Checked is transitive. If a Checked<> value which has overflowed is used again to compute anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r Checked<> value cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflowed state will be copied. Therefore if we reach this code and m_accumulatedStringsLength has overflowed (as in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 earlier example) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n outputStringSize will also be deemed to have overflowed, even if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 totalSeparactorsLength + m_accumulatedStringsLength calculation doesn’t itself overflow.)

m_separator is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 separator string we passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 javascript Array.prototype.join method (or , if we didn’t pass one.) This code is computing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 total length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result string by multiplying 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 separator string by one less than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array length, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n adding that to m_accumulatedStringsLength. These calculations are clearly prone to integer overflow and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch also added cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Checked template here.

One thing is different here though: m_accumulatedStringsLength became Checked<unsigned, RecordOverflow> but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 three variables used here have all become Checked<size_t, RecordOverflow>. This means that if we reach this code, and importantly if m_accumulatedStringsLength hasn’t overflowed, 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ý bet365se three Checked<> variables will only detect overflows which exceed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 range of a size_t (which is 64-bits wide.)

So by also passing a long separator string to Array.prototype.join, and making sure that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 combined length of all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 strings in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array doesn’t itself overflow an unsigned int, we can get finalSize to exceed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 range of an unsigned int without triggering any of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer overflow checks. This isn’t a security bug though yet, but following cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code forwards we see that finalSize is immediately passed to joinStrings:

outputStringImpl = joinStrings(m_strings, m_separator, finalSize);

The prototype of that function is:

template
static inline PassRefPtr joinStrings(const Vector& strings, const String& separator, unsigned outputLength)

The third parameter of joinStrings is an unsigned int, so when finalSize (a size_t) gets passed to this function it will be truncated from 64-bit to 32-bits.

This is body of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner::joinStrings function:

CharacterType* data;
RefPtr outputStringImpl = StringImpl::tryCreateUninitialized(outputLength, data);
if (!outputStringImpl)
   return PassRefPtr();

const String firstString = strings.first();
appendStringToData(data, firstString);

for (size_t i = 1; i < strings.size(); ++i) {
 appendStringToData(data, separator);
 appendStringToData(data, strings[i]);
}

StringImpl::tryCreateUninitialized will malloc a buffer large enough to contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 StringImpl header followed by a buffer for outputLength characters and return a pointer to that character buffer in data (which is passed by reference.)

appendStringToData is a simple memcpy-like function which copies characters from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string passed as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second argument to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data buffer passed as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument (which is again a pointer passed by reference.)

By triggering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer truncation in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to this function we can force outputLength to be shorter than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual length of all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 strings which will end up being copied in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 appendStringToData calls, meaning that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will start to write outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bounds of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated string. Note however that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 minimum length of data that will get written out-of-bounds is over 4 gigabytes, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 total length must be >= 2^32 to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 truncation, and that truncation will have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 effect of subtracting at least 2^32 from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length which will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be passed to tryCreateUninitialized.

Exploiting unbounded copies


Perhaps cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most well-known example of an exploit involving an unbounded copy is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Apache on BSD negative memcpy [ https://web.archive.org/web/20040319164357/http://securityfocus.com/archive/1/278270/2002-06-17/2002-06-23/0 ]. Here cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were able to exploit a unbounded memcpy onto cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack by overwriting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remaining length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copy (which was stored on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack) due to a quirk of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BSD memcpy implementation. I also recently reported a integer overflow in python which required a similar trick to exploit: [ https://hackerone.com/reports/6389 ]

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case of this JavaScriptCore bug cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is one fundamental insight that will allow us to exploit it: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 total length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copy is based on values read from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copy, and this bug lets us corrupt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap.

In order to bound cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory copying loop and let us turn this into a controlled heap buffer overflow we're going to have to set up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap in a very exact way such that we're able to corrupt all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 strings which are involved in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copy (truncating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m) whilst also corrupting something else useful for getting code execution.

At this point it’s worth clarifying what all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 different string types which we’ve seen so far are:

JSC::JSString is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string object which javascript manipulates. These are garbage-collected and live on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JavaScriptCore GC heap, not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main process heap. This object doesn’t contain any string character data but has a member variable of type WTF::String:

WTF::String is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main string type used in WebKit. It too however doesn’t actually contain any character data; its only member variable is a reference-counted pointer to a WTF::StringImpl:

WTF::StringImpl is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual underlying string type which both JSString and String are built from. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 in-memory layout of a StringImpl we can see it stores cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of each string inline, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore it should be quite easy to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 m_length field to 0:

class StringImpl {
 unsigned m_refCount;
 unsigned m_length;
 union {
   const LChar* m_data8;
   const UChar* m_data16;
 };
 union {
   void* m_buffer;
   StringImpl* m_substringBuffer;
   mutable UChar* m_copyData16;
 };
 mutable unsigned m_hashAndFlags;
}

(The character data of a StringImpl is stored inline, directly following this header.)

Note also that javascript strings have no byte restrictions, it’s perfectly valid to have a string containing null bytes, so overwriting fields with zero is quite possible.

The heap


Strings in JavaScriptCore are allocated using fastMalloc which is in fact just tcmalloc. There are already some great resources for learning about tcmalloc internals: this talk from Sean Heelan and Agustin Gianni gives a good overview of tcmalloc exploitation [ https://immunityinc.com/infiltrate/archives/webkit_heap.pdf ]. The tcmalloc code itself is also quite readable [ https://code.google.com/p/gperftools/ ].

There are two major things to understand about tcmalloc for heap overflow exploitation:
  • By forcing enough allocations of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size we can force subsequent allocations of that size to be next to each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r in memory, with each new allocation being at a lower address until after a certain number of allocations cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 addresses will jump up again.
  • Free lists are Last-In-First-Out: if you free an object cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next allocation of an object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size is very likely to get allocated where that free’d object was.

This is a very simplified explanation but it’s enough for this exploit. Check out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tcmalloc specific links to understand exactly how and why this happens.

We’re aiming to use those two behaviours of tcmalloc to “groom” something like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following heap layout: (for some background on heap manipulation check out Alex Sotirov’s Heap Feng-Shui research from 2007 [ http://www.phreedom.org/research/heap-feng-shui/heap-feng-shui.html ])


undersized buffer is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer which joinStrings will allocate to copy all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copies of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 strings in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner into. What we’re aiming to do is line up following this allocation in memory any strings which we used to build up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array (so that we can overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir length fields with 0) followed by a target object we want to overwrite.

Leaking useful addresses


My high level exploitation strategy for this bug is to trigger it twice: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first time setting things up to create an infoleak which will allow us to defeat ASLR and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second time round setting things up to overwrite a vtable pointer and pivot to a ROP stack.

Fermin Serna’s “Info leak era” talk [ https://media.blackhat.com/bh-us-12/Briefings/Serna/BH_US_12_Serna_Leak_Era_Slides.pdf ] gives a good overview of common techniques used to turn various bug classes into infoleaks. Fermin mentions overwriting string length fields to be able to read off of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end, and looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 layout of a StringImpl we can see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length field comes before 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 inline data. This means that if we can set up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap such that we can overwrite just cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length field we’ll be able to read off of 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 string from javascript:


On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 left is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap layout we’ll try to groom, it consists of 5 objects: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 undersized buffer which joinStrings allocated - this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer which if we do nothing else more than 4GB will be copied into. Following this are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two strings which will form almost all 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. These are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 strings which we want to truncate by setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir lengths to 0. We need two strings since we have to be able to control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer truncation exactly so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 undersized buffer is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right size and 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 overwrite string is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right length. By using two strings with one character difference in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir lengths we can easily truncate to any length by calculating how many copies of each string should be in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array.

Following cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 StringImpl which we’ll overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of and use for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 infoleak. Finally, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fifth object is an HTMLLinkElement; we want to read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable of this object.

The string on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right of this diagram will be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first element in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array to be joined and consequently will be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only string which will actually be copied into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 undersized buffer (if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 grooming works.) This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string which will completely overwrite source string and separator string (setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir lengths to 0) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length field of leak string (setting it to 0xffffffff.) It doesn’t matter where on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap this string is allocated.

Allocation and free primitives


Due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nature of tcmalloc getting allocations to line up in memory is very easy, simply allocate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m one after 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 in reverse order and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's a good probability it'll work (good enough for this contest at least.)

In order to start getting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se contiguous memory allocations we need a malloc primitive we can trigger from javascript. For this we can just use javascript strings, since as we saw cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're actually just wrappers around cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 StringImpl type. JavaScriptCore does however use one optimization we have to be aware of: when using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 addition operator ‘+’ to connect strings JSC won’t create a brand new string but instead will create a JSRopeString which has two pointers, one to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 left of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘+’ and one to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right.

These rope strings won’t help us make controlled size allocations, however looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of JSRopeString we can see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSRopeString::resolveRope method which ‘flattens’ cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string by allocating a new StringImpl large enough for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole string cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n copying all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sections of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rope into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right place. This flatten operation can be triggered on a javascript string by simply indexing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first character allowing us to build a simple alloc() function:

/* helper function to build strings which have a power-of-two length */
function pow2str(p, b) {
 var str = String.fromCharCode(b);
 for (; p; p--){
   str += str;
 }
 return str;
}

/* build a string of any length
* note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual malloc’ed size will include cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 StringImpl header size */
function alloc(n, b) {
 var res = '';
 for(var i = 0; i < 32; i++){
   if(n & 0x1)
     res += pow2str(i, b);
   n >>= 1;
 }
 /* this will flatten cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rope and actually make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation */
 res[0];
 return res;
}

We can allocate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first four objects for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 groom in quick succession (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HTMLLinkElement and three strings) but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 undersized buffer will only be allocated after we’ve built cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire array which will be joined and called join. Since this array will have a few million entries building it is likely to cause some heap churn and it’s very unlikely that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re will be no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r heap allocations of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target size we're trying to groom. Therefore it would be useful to have a free primitive such that we can allocate a placeholder object where we would like undersized buffer to end up, build cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n free cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 placeholder right before calling join to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug. As tcmalloc’s freelists are LIFO we’re much more likely to end up getting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 undersized buffer allocation in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right place if we can free cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 placeholder object reliably.

One option is to use javascript strings again: by removing all references to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n forcing a garbage collection we can get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying StringImpl to be free’d. Unfortunately cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no API exposed to javascript for forcing a GC so we’re left having to trigger one manually, usually by making many allocations. This can be very noisy and unreliable - it’s hard to know when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GC has actually occurred. It would be much better if we could find a way to directly cause an allocation and free of a buffer of a controlled size from javascript. The tcmalloc presentation linked to earlier suggested leveraging a StringBuilder to do this but I chose to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same JSStringJoiner we’ve already been looking at to build a free primitive:

The JSStringJoiner constructor will create a Vector m_strings to hold all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Strings which will be joined, reserving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 estimated capacity:

inline JSStringJoiner::JSStringJoiner(const String& separator, size_t stringCount)
 : m_separator(separator)
 , m_isValid(true)
 , m_is8Bits(m_separator.is8Bit())
{
 ASSERT(!m_separator.isNull());
 m_isValid = m_strings.tryReserveCapacity(stringCount);
}

stringCount is completely controlled, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Vector backing storage will be allocated on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap giving us a controlled heap allocation. In arrayProtoFuncJoin as we saw earlier a JSStringJoiner is created on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack, which means that after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array has been joined and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSStringJoiner goes out of scope cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 m_strings vector will be destructed and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 backing storage will be free’d. All we need to be able to do is execute arbitrary javascript while this array is being joined which we can do easily by setting a toString function on one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 elements of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array like this for example:

function doNoisyThing(){...}

var arr = []
arr.push({toString: doNoisyThing})
for(var i = 1; i < 0x1a0/8;i++){
 arr.push("");
}

The function doNoisyThing() is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n free to make any allocations it needs. The join method when called on arr will make a 0x1a0 byte heap allocation, call doNoisyThing() (indirectly via a toString method) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n free that 0x1a0 byte heap allocation. For example, after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following snippet executes c, b and a are likely to be contiguous on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap, no matter what doNoisyThing did:

var a = alloc(0x1a0 - 0x20, ‘A’);
var b = alloc(0x1a0 - 0x20, ‘B’);
arr.join(); // will call doNoisyThing
var c = document.createElement(“HTMLLinkElement”); // 0x1a0 bytes

Leaking useful things


We’re now at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point where we can groom cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap and trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow to unbound cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 infoleak string allowing us to read beyond its bounds. Why did we groom an HTMLLinkElement in particular after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leak string? HTMLLinkElement is actually very useful as it allows us to leak not only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 load address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebCore library in memory but also to leak cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 addresses of arbitrary strings:

WebCore base address leak

We can compute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 load address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebCore library by reading cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable pointer of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HTMLLinkElement and subtracting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 known offset of that vtable in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library.

Arbitrary javascript string address leak

HTMLLinkElement has two String members: m_type and m_media. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HTMLLinkElement::parseAttribute function we can see that we can control m_type easily from javascript:

void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
 [...]
 } else if (name == typeAttr) {
   m_type = value;
 [...]

By setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type attribute of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 groomed HTMLLinkElement to a string from javascript and reading cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 m_type field using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unbounded infoleak string we can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying character data. The final step is to make sure to keep hold of a reference to those strings to ensure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y don’t get garbage-collected and free’d.

Code execution


For code execution we set up a similar heap groom to that which we used for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 infoleak, except we don’t need cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 infoleak string this time:

We can build a fake vtable as a javascript string and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string infoleak technique to find its address. We cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow and overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable pointer of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HTMLLinkElement to point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 controlled vtable. Having done this cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 renderer will almost instantly call a virtual function on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HTMLLinkElement we just corrupted as during garbage collection (which happens frequently) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual eventTargetData method will be called. This virtual function pointer is at offset 0x60 in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable, meaning that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value at that offset into our fake vtable string will be called. This call instruction is of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 form:

 call [rax + 0x60]

meaning that rax points to our controlled fake vtable. We just need to find a suitable sequence of instructions which will let us pivot cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack to rax. At offset 0x1f6235 in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebCore library we can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following instructions:

 push rax
 pop rsp
 pop rbp
 ret

Executing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se instructions will set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack pointer to point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fake vtable string, so if we’re careful about how we build that string we can use it as both a fake vtable and a ROP stack.

ROP payload


At this point we’ve achieved native code execution; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last step for part I is to load a secondary payload and execute it. For this I’m using a very simple ROP stack which writes a dynamic library to disk and calls dlopen to load it allowing me write cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real payload in C. Take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 linked exploit to see how this ROP stack actually works.

We’ll look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of sandboxing in detail in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next post, but it suffices for now to see that this line:

(allow file-read* file-write* (home-subpath "/Library/Keychains"))

in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox definition file for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 web process means that we can read and write arbitrary files in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s ~/Library/Keychains folder from inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Safari renderer sandbox. The ROP stack opens a file in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re, writes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of a dynamic library to it and calls dlopen to load it.

For now that payload library is simply this:

#include

__attribute__((constructor))
static void init(void){
 SpeakString("\x06pwned!");
}

In part II we’ll replace this payload with a kernel exploit allowing us to break out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox.

You can take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complete exploit here [ https://code.google.com/p/google-security-research/issues/detail?id=77 ]. It’s been edited from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual one thrown at CanSecWest to target this [ http://builds.nightly.webkit.org/files/trunk/mac/WebKit-SVN-r161944.dmg ] old nightly build which is also vulnerable and easy to test with if you want to fire up a debugger and try it out. All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 offsets and assembly snippets in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write-up are also from that build.

Tuesday, July 15, 2014

Announcing Project Zero

Posted by Chris Evans, Researcher Herder

Security is a top priority for Google. We’ve invested a lot in making our products secure, including strong SSL encryption by default for Search, Gmail and Drive, as well as encrypting data moving between our data centers. Beyond securing our own products, interested Googlers also spend some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir time on research that makes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet safer, leading to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 discovery of bugs like Heartbleed.

The success of that part-time research has led us to create a new, well-staffed team called Project Zero.

You should be able to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 web without fear that a criminal or state-sponsored actor is exploiting software bugs to infect your computer, steal secrets or monitor your communications. Yet in sophisticated attacks, we see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of “zero-day” vulnerabilities to target, for example, human rights activists or to conduct industrial espionage. This needs to stop. We think more can be done to tackle this problem.

Project Zero is our contribution, to start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ball rolling. Our objective is to significantly reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of people harmed by targeted attacks. We’re hiring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best practically-minded security researchers and contributing 100% of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir time toward improving security across cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet. 

We’re not placing any particular bounds on this project and will work to improve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security of any software depended upon by large numbers of people, paying careful attention to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 techniques, targets and motivations of attackers. We’ll use standard approaches such as locating and reporting large numbers of vulnerabilities. In addition, we’ll be conducting new research into mitigations, exploitation, program analysis—and anything else that our researchers decide is a worthwhile investment.

We commit to doing our work transparently. Every bug we discover will be filed in an external database. We will only report bugs to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 software’s vendor—and no third parties. Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug report becomes public (typically once a patch is available), you’ll be able to monitor vendor time-to-fix performance, see any discussion about exploitability, and view historical exploits and crash traces. We also commit to sending bug reports to vendors in as close to real-time as possible, and to working with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to get fixes to users in a reasonable time.

We’re hiring. We believe that most security researchers do what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y do because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y love what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y do. What we offer that we think is new is a place to do what you love—but in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open and without distraction. We’ll also be looking at ways to involve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wider community, such as extensions of our popular reward initiatives and guest blog posts. As we find things that are particularly interesting, we’ll discuss cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m on this blog, which we hope you’ll follow.