Firefox an integer overflow leading to the mmap region is out of bounds write use-vulnerability warning-the black bar safety net


This article will explore a very interesting Vulnerability---CVE-2016-9066, a very simple but very interesting could lead to code execution Firefox vulnerability. The code in the presence of an integer overflow vulnerability, leading to loading of mmap area bounds. There is an advantage of this method is that the JavaScript stack in the buffer back, and then overflow to its meta-data to create a false idle unit. Then the ArrayBuffer created instance is placed in another ArrayBuffer inline data. Then can arbitrarily modify the internal ArrayBuffer, generating arbitrary read and write. And can easily achieve code execution. The complete vulnerability report can be found here, this is for MacOS 10.11.6 on Firefox 48.0.1 were tested. Bugzilla bug report can be found here. The Vulnerability The following code is used to load the script tag of the data: the result nsScriptLoadHandler::TryDecodeRawData(const uint8_t* aData, a uint32_t that aDataLength, bool aEndOfStream) { int32_t srcLen = aDataLength; const char* src = reinterpret_cast(aData); int32_t dstLen; nsresult rv = mDecoder->a getmaxlength(src, srcLen, &dstLen); NS_ENSURE_SUCCESS(rv, rv); a uint32_t that haveRead = mBuffer. length(); a uint32_t that capacity = haveRead + dstLen; if (! mBuffer. reserve(capacity)) { return NS_ERROR_OUT_OF_MEMORY; } rv = mDecoder->Convert(src, &srcLen, mBuffer. begin() + haveRead, &dstLen); NS_ENSURE_SUCCESS(rv, rv); haveRead += dstLen; MOZ_ASSERT(haveRead MOZ_ALWAYS_TRUE(mBuffer. resizeUninitialized(haveRead)); return NS_OK; } When new data from the server arrives, the code will be OnIncrementalData call. Here the bug is a simple integer overflow occurs when the server sends more than 4GB of data. In this case, the capacity will wrap around, and call mBuffer. reserve, but will not in any way modify the buffer. mDecode->Convert and then in the buffer at the end to write more than 8GB of data, the data in the browser is stored as a char16_t, which will consist of a mmap block is a common, very large mmap block support under the complete. The patch is also very simple: a uint32_t that haveRead = mBuffer. length(); \- a uint32_t that capacity = haveRead + dstLen; \- if (! mBuffer. reserve(capacity)) { + \+ CheckedInt capacity = haveRead; \+ capacity += dstLen; + \+ if (! capacity. isValid() || ! mBuffer. reserve(capacity. value())) { return NS_ERROR_OUT_OF_MEMORY; } First, look not so reliable. For example, it needs to send and to allocate multiple gigabytes of memory. However, we will see that the bug may in fact be very reliable use, and in my 2015 version of the MacBook Pro open on the page after about one minute to complete the vulnerability trigger. We will now first discuss how to use this bug in macOS on the pop-up a calculator, and then improve the exploit's reliability, and use less bandwidth, we will use HTTP compression. Exploit #include #include const size_t MAP_SIZE = 0x100000; // 1 MB int main() { char* chunk1 = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); char* chunk2 = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); printf("chunk1: %p - %p\n", chunk1, chunk1 + MAP_SIZE); printf("chunk2: %p - %p\n", chunk2, chunk2 + MAP_SIZE); return 0; } The above program prints a result, can tell us through a simple mmap, the mapping memory until there is space to be filled, and then through the mmap allocates a block of memory to allocate overflow buffer behind the things. To verify this, we will perform the following operations: Load script(包含 payload.js will cause overflow of the code) and some asynchronous execution of JavaScript code(code.js to perform the following step 3 and step 5) When the browser requests the payload. js, let the server reply Content-Length for 0x100000001, but only the transmission data of the first 0xffffffff bytes Then, let the JavaScript code to assign a plurality of large enough(1GB)ArrayBuffers memory will not necessarily be used until it is actually written to the buffer Let the webserver send the payload. js the remaining two bytes Check each of the ArrayBuffer of the first few bytes, there is a should be included by the webserver to send the data In order to achieve this, we will need to run in the browser the JavaScript code and the[web server](<http://www.myhack58.com/Article/sort099/sort0100/Article_100_1.htm>)between some kind of synchronization primitive. For this reason, I'm on python's asyncio library, the above has written a small[web server](<http://www.myhack58.com/Article/sort099/sort0100/Article_100_1.htm>) **[1] [[2]](<84623_2.htm>) [[3]](<84623_3.htm>) [[4]](<84623_4.htm>) [next](<84623_2.htm>)**