This is a friendly warning that your web-browser does not currently protecting your privacy and/or security as well as you might want. Click on this message to see more information about the issue(s) that were detected. November 23rd, 2016 Chrome blink Speech­Recognition­Controller use-after-free

Chrome blink Speech­Recognition­Controller use-after-free

(Chromium 455857, CVE-2015-1251)

Synopsis

A specially crafted web-page can cause the blink rendering engine used by Google Chrome and Chromium to continue to use a speech recognition API object after the memory block that contained the object has been freed. An attacker can force the code to read a pointer from the freed memory and use this to call a function, allowing arbitrary code execution.

Known affected software and attack vectors

  • Google Chrome 39.0

    An attacker would need to get a target user to open a specially crafted webpage. Disabling Javascript should prevent an attacker from triggering the vulnerable code path.

Repro.html <html> <head> <script> o­Window = window.open(); o­Webkit­Speech­Recognition = new o­Window.webkit­Speech­Recognition(); o­Window.close(); set­Interval(function(){ if (o­Window.closed) { o­Webkit­Speech­Recognition.start(); } }, 10); </script> </head> </html>

Description

Creating a webkit­Speech­Recognition Javascript object in a popup window before closing the popup frees a C++ object used internally by the speech recognition API code but leaves a dangling pointer to the freed memory in another C++ object. When the start() Javascript method is called, this dangling pointer is used to try to read a function pointer from a virtual function table and call that function. An attacker has ample time to groom the heap between the free and re-use in order to control the function pointer used by the code, allowing arbitrary code execution.

This sequence of events describes the process happening in the repro:

  1. When a new window is opened from Javascript, a C++ Speech­Recognition­Client­Proxy object is instantiated.

  2. When a new webkit­Speech­Recognition object is created in Javascript, a Speech­Recognition C++ object is created to back it up internally.

  3. In the constructor of the Speech­Recognition C++ object, the m_­controller member variable is initialized by creating a new Speech­Recognition­Controller C++ object using Speech­Recognition­Controller::from.

    speech/Speech­Recognition.cpp:

    Speech­Recognition::Speech­Recognition(Execution­Context* context)
    /* <<<snip>>> */
        m_­controller = Speech­Recognition­Controller::from(page);
        ASSERT(m_­controller);
    /* <<<snip>>> */
    
  4. In the constructor of the Speech­Recognition­Controller C++ object, the m_­client member variable is initialized by storing a pointer to the Speech­Recognition­Client­Proxy C++ object created in step 1.

    speech/Speech­Recognition­Controller.cpp:

    Speech­Recognition­Controller::Speech­Recognition­Controller(Pass­Own­Ptr<Speech­Recognition­Client> client)
        : m_­client(client)
    /* <<<snip>>> */
    
  5. When the window created in step 1 is closed, the Speech­Recognition­Client­Proxy C++ object created in step 1 is destroyed and the memory previously used to store the object is freed.

  6. When the start Javascript method of the webkit­Speech­Recognition object created in step 2 is called, the start C++ method of the Speech­Recognition­Controller object is called internally. This method in turn calls the start C++ method of the previously freed Speech­Recognition­Client­Proxy object through its m_­client member variable.

    speech/Speech­Recognition.cpp:

    void Speech­Recognition::start(Exception­State& exception­State)
    /* <<<snip>>> */
        m_­controller->start(/* <<<snip>>> */);
    /* <<<snip>>> */
    

    speech/Speech­Recognition­Controller.h:

    void start(/* <<<snip>>> */)
    {
        m_­client->start(/* <<<snip>>> */);
    }
    

    In the last code snippet, when this code is executed, the m_­client member no longer points to a valid object, as this object has been deleted and its memory freed.

Exploit

An attacker looking to exploit this issue is going to want to try and control the contents of the freed memory, before getting the code to use the dangling pointer to call a virtual function. Doing so would allow an attacker to execute arbitrary code. This is made possible because steps 5 and 6 can both be triggered at a time of the attackers choosing, giving the attacker the ability to free the memory in step 5 whenever this is convenient and attempt to reallocate and fill it with any data before executing step 6. This should allow an attacker to create a fake vftable pointer and gain arbitrary code execution. In order to develop a working exploit, existing mitigations will need to be bypassed, most significantly ASLR and DEP. As this vulnerability by itself does not appear to allow bypassing these mitigations, I did not develop a working exploit for it.

Time-line

  • November 2014: This vulnerability was found through fuzzing.
  • December 2014: This vulnerability was submitted to ZDI and i­Defense.
  • January 2015: This vulnerability was acquired by ZDI.
  • February 2015: This vulnerability was fixed in revision 190993.
  • May 2015: This vulnerability was addressed by Google in Chrome 43.0.2357.65.
  • November 2016: Details of this issue are released.
Bug­Id report: chrome_­child.dll!blink::Speech­Recognition::start Arbitrary AVE(6AD71ABA)
id:             chrome_­child.dll!blink::Speech­Recognition::start Arbitrary AVE(6AD71ABA)
description:    Security: Attempt to execute non-executable arbitrary memory (@0x0501B300) in chrome_­child.dll!blink::Speech­Recognition::start
note:           Based on this information, this is expected to be a security issue!
This report was generated using a predecessor of Bug­Id, a Python script created to detect, analyze and id application bugs. Don't waste time manually analyzing issues and writing reports but try Bug­Id out yourself today! You'll get even better reports than this one with the current version.
© Copyright 2017 by Sky­Lined. Last updated on August 19th, 2017. Creative Commons License This work is licensed under a Creative Commons Attribution-Non‑Commercial 4.0 International License. If you find this web-site useful and would like to make a donation, you can send bitcoin to 183yyxa9s1s1f7JBp­PHPmz­Q346y91Rx5DX.