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.
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.
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
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.
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.
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.
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.
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.
It allocates arrays and forces heap allocation by using slice() and concatenation operation.
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.
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.
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.
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.
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.
|175903||Debian Security Update for icedove (DSA 3730-1)|
|169429||SUSE Enterprise Linux Security Update for MozillaFirefox,
|169420||SUSE Enterprise Linux Security Update for MozillaFirefox
|236204||Red Hat Update for Thunderbird Security (RHSA-2016:2850)|
|196649||Ubuntu Security Notification for Thunderbird Vulnerabilities
|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
|157334||Oracle Enterprise Linux Security Update for firefox
|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
|370245||Mozilla Firefox SVG Animation Remote Code Execution Vulnerability (MFSA2016-92)|