Firefox SVG Animation Remote Code Execution CVE-2016-9079

Introduction:

A zero day exploit against Tor Browser and FireFox has been observed in the wild. The exploit is initiated when a target accesses a compromised web page or web page hosted by an attacker. The vulnerability has been assigned CVE Id – 2016-9079, Bugzilla id – 1321066. The exploit targets a use after free vulnerability in Firefox SVG animation component and allows remote code execution. The vulnerability has been patched in Firefox 50.0.2, Firefox ESR 45.5.1, Thunderbird 45.5.1 and Tor Browser 6.0.7.

Vulnerability:

Scalable Vector Graphics (SVG) is an XML-based markup language that described two-dimensional vector graphics. As per the MDN documentation “SVG is essentially to graphics what HTML is to text.” It is similar to Flash technology, the difference is, it is a text-based open Web standard. SVG is compatible with CSS, DOM and SMIL.

As mentioned earlier the exploit targets a user after free vulnerability(UAF) in Firefox SVG component. As the name suggests the UAF occurs when the application refers to a memory location which has been freed, causing it to crash, behave abnormally etc. It is important to note that not all UAF vulnerabilities are exploitable, some application have logical constraints which fails to prevent UAF, however they are able to safely crash the application and avoid compromising user security. One scenario where UAF can occur is when we are traversing an array/object and refer to the said array/object after it has been freed or reallocated. In our case, Firefox fails to validate an iterator in nsSMILTimeContainer::NotifyTimeChange().

A ‘nsSMILTimeContainer’ object is created for every <svg> element and each element will have its own ‘mMilestoneEntries’ array to keep track of tim e intervals. When we call pauseAnimations() it suspends the clock for all animations within the specified svg component.

NotifyTimeChange()
NotifyTimeChange()

pauseAnimations() calls NotifyTimeChange() which is iterating over “mMilestoneEntries” array via pointer “p” and the object may be modified by calling “HandleContainerTimeChange()”, which can in turn lead to NotifyChangedInterval() & HandleChangedInterval(). HandleChangedInterval() is called when an entry in mMilestoneEntry array is relative/dependent to another. The function also checks if the dependent values are part of the same ‘nsSMILTimeContainer’, if not it updates the mMilestoneEntry array by calling UpdateCurrentInterval(). The update can lead to creation of a new array entry causing it relocate and free the original memory allocation. At a certain point ”p->mTimebase.get()” in NotifyTimeChange() will result in UAF because get() is called after UpdateCurrentInterval().

The exploit generates an html page which consists of two separate <svg> components and they contain animations whose time intervals are dependent on each other, this ensures that UpdateCurrentInterval() will be called when animations are paused. The code snippet below 

Exploit:

The exploit for this vulnerability has been released to public in tor-talk. This exploit applies only to Windows operating system as the code relies on the functions defined in kernel32.dll. It consists of two files HTML(index.html) and javascript(csbanner.js), they communicate with each other via the worker API. The .js file performs the heap allocation and writing the shellcode in the memory chunks and linking them for execution via a ROP chain. The HTML file creates the web page and waits for the .js file to finish heap spraying and triggers the bug in the SVG component by calling “pauseAnimations()”.

Trigger:

A little background information is required to understand the effects of pauseAnimations(). In simple terms SVG component is a container for elements that are to be animated. And we use the “<animate>” tag to define the animation and it is attributes like begin,end, from etc. An element can have multiple begin and end times, So we use these time values and conditions to calculate intervals. The element is animated over these intervals.  

As mentioned earlier the code within NotifyTimeChange() function causes the UAF to occur. Based on the stack traces provided in the Bugzilla ticket, we can see the function calls leading to NotifyTimeChange(). Which clearly shows the crash when “get()” is called over an undefined object.

Crash log
Crash log

Exploit Code:

The .html  contains the shellcode, it is stored as a string in the variable ‘thecode’ . This is passed to the .js file as input. The shellcode is obfuscated, a detailed analysis is provided here.

Shellcode
Shellcode

Then it checks for the version of Firefox version through the user agent. The expression validates Firefox version 47 and greater. This check is used to set the offset variable.

Firefox version check
Firefox version check

After the version checks the svg components are added to the html document. The structure of the svg components is given below. The value idX, idA, idB, idC evaluates to ‘‘id’ followed by random alphanumeric string of 4 characters. 

svg code
svg code

Note that the end time interval for  “idB” and “idC” are relative to “idC” and “idA” respectively. This ensures that UpdateCurrentInterval() is called when the animations are paused. After the svg components are added it waits for the csbanner.js file to post the base address of heap. Once it is received the html file will trigger the UAF vulnerability causing the browser to execute the shellcode.

Heap Allocation:

It allocates arrays and forces heap allocation by using slice() and concatenation operation.

Heap allocation
Heap allocation

After allocation the heaps are sprayed with the shellcode, the address of the heap is used to initialize the rop chain. The next step would be to change the state of the allocated heap to have execution privilege, this done to bypass DEP (Data Execution Prevention). To do this we use the rop chain, to execute ‘VirtualAlloc()‘ to change the state of the memory blocks. It tries to convert the heap blocks to commit pages with read/write execute protection.

DEP bypass
DEP bypass

After allocating space it fills it with the shellcode to call “CreateThread()” and executes the shellcode stored in the heap to  send machine information out via tcp port 80.

Conclusion:

The UAF vulnerability is  fixed in versions Firefox 50.0.2, Firefox ESR 45.5.1, Thunderbird 45.5.1 and Tor Browser – 6.0.7. The bug was filed on 2016-11-29 12:12. The fix was to make a copy of the elements from mMilestoneEntries array before making any function calls through them.

Fix
Fix

The code snippet above shows the elements of ‘mMilestoneEntries’ being appended to array ‘elems’ and it is followed by a second for loop which iterates of the copy array and calls ‘HandleContainerTimeChange’. We request our customers to scan their machines with the QID’s listed below.

Note:

A metasploit module is also available under the name of firefox_smil_uaf it is listed under exploit/windows/browser. The exploit is designed for x86 architecture.

QID Title
175903 Debian Security Update for icedove (DSA 3730-1)
169429 SUSE Enterprise Linux Security Update for MozillaFirefox,
mozilla-nss (SUSE-SU-2016:3080-1)
169420 SUSE Enterprise Linux Security Update for MozillaFirefox
(SUSE-SU-2016:3048-1)
236204 Red Hat Update for Thunderbird Security (RHSA-2016:2850)
196649 Ubuntu Security Notification for Thunderbird Vulnerabilities
(USN-3141-1)
276238 Fedora Security Update for firefox (FEDORA-2016-d2cbcd602d)
276237 Fedora Security Update for thunderbird (FEDORA-2016-fde083842e)
157335 Oracle Enterprise Linux Security Update for thunderbird
(ELSA-2016-2850)
157334 Oracle Enterprise Linux Security Update for firefox
(ELSA-2016-2843)
236202 Red Hat Update for Firefox Security (RHSA-2016:2843)
175898 Debian Security Update for firefox-esr (DSA 3728-1)
196637 Ubuntu Security Notification for Firefox Vulnerabilities
(USN-3140-1)
370245 Mozilla Firefox SVG Animation Remote Code Execution Vulnerability (MFSA2016-92)

References:

Tor security advisory: Old Tor Browser Bundles vulnerable
Firefox SVG Animation Remote Code Execution
[tor-talk] Javascript exploit
Bugzilla ticket

Leave a Reply

Your email address will not be published. Required fields are marked *