(Chromium 455857, CVE-2015-1251)
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.
Google Chrome 39.
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.
Creating a webkitSpeechRecognition
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:
When a new window is opened from Javascript, a C++
SpeechRecognitionClientProxy
object is instantiated.
When a new webkitSpeechRecognition
object is created in Javascript, a
SpeechRecognition
C++ object is created to back it up internally.
In the constructor of the SpeechRecognition
C++ object, the m_controller
member variable is initialized by creating a new
SpeechRecognitionController
C++ object using
SpeechRecognitionController::
.
speech/SpeechRecognition.
SpeechRecognition:: SpeechRecognition(ExecutionContext* context)
/* <<<snip>>> */
m_controller = SpeechRecognitionController:: from(page);
ASSERT(m_controller);
/* <<<snip>>> */
In the constructor of the SpeechRecognitionController
C++ object, the
m_client
member variable is initialized by storing a pointer to the
SpeechRecognitionClientProxy
C++ object created in step 1.
speech/SpeechRecognitionController.
SpeechRecognitionController:: SpeechRecognitionController(PassOwnPtr<SpeechRecognitionClient> client)
: m_client(client)
/* <<<snip>>> */
When the window created in step 1 is closed, the
SpeechRecognitionClientProxy
C++ object created in step 1 is destroyed
and the memory previously used to store the object is freed.
When the start
Javascript method of the webkitSpeechRecognition
object
created in step 2 is called, the start
C++ method of the
SpeechRecognitionController
object is called internally. This method in
turn calls the start
C++ method of the previously freed
SpeechRecognitionClientProxy
object through its m_client
member
variable.
speech/SpeechRecognition.
void SpeechRecognition:: start(ExceptionState& exceptionState)
/* <<<snip>>> */
m_controller->start(/* <<<snip>>> */);
/* <<<snip>>> */
speech/SpeechRecognitionController.
:
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.
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.
This report was generated using a predecessor of BugId, a Python script created to detect, analyze and id application bugs. Don't waste time manually analyzing issues and writing reports but try BugId out yourself today! You'll get even better reports than this one with the current version.id: chrome_child.dll!blink:: SpeechRecognition:: start Arbitrary AVE(6AD71ABA) description: Security: Attempt to execute non-executable arbitrary memory (@0x0501B300) in chrome_child. dll!blink:: SpeechRecognition:: start note: Based on this information, this is expected to be a security issue!