SSD Advisory – Firefox JavaScript Type Confusion RCE

Vulnerabilities Summary
A vulnerability in register allocation in JavaScript can lead to type confusion, allowing for an arbitrary read and write, which leads to remote code execution inside the sandboxed content process when triggered.

Vendor Response
The reported security vulnerability was fixed in Firefox 62.0.3 and Firefox ESR 60.2.2.

CVE
CVE-2018-12386

Credit
Independent security researchers, Niklas Baumstark, Samuel Groß and Bruno Keith, had reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program.

Affected systems
Firefox 62.0
Firefox ESR 60.2

Vulnerability Details
While fuzzing Spidermonkey(Mozilla’s JavaScript engine written in C and C++), we trigger a debug assertion with the following minimized sample:

Which triggered the following assertion in the register allocator:

This implies that somehow a wrong register is being used somewhere in the emitted code.

Root Cause Analysis
The function described above produces the following basic blocks:

The backtracking allocator decides on the following allocations:

Now BacktrackingAllocator::resolveControlFlow adds moves (via MoveGroup LIR statements) to account for the phi and the distinct ranges of v3 in the two blocks.It introduces a MoveGroup [rax -> stack:8] to the beginning of block 2 to change the v3 location and int.And it introduces a MoveGroup [stack:16 -> rax] to the end of block 0 to resolve the phi. These two changes conflict with each other: Instead of v3, v16 = v6 will be located at stack:8.

Visualization:

Conditions:
In order for this to occur we require the following conditions:
1. Two blocks A and B with a control flow edge A -> B
2. Vreg v1 that has distinct allocations x in A and y in B
3. a phi vreg v2 that has allocation x in B

This will introduce the problematic pattern:

With some manual experimenting, the register misallocation can be turned into a type confusion. The basic idea is to compile a function that takes two arguments, one of type X and one of type Y. The function then generates optimized code based on the speculated types and adds runtime guards to ensure that the speculations still holds.

However, due to the register misallocation, the register holding the value of type X is now overwritten with the value of type Y, causing the type confusion. The following code demonstrates this:

This code will be compiled such that in the last statement, when the inline property x of a is accessed, it will actually access the inline property y of b due to the register misallocation and the fact that x and y are stored at the same offset in the objects. As it expects the loaded property to be a double, it will return the loaded value as number. Since it now loads property y it returns a pointer as a double, resulting in an info leak. Note that for this PoC to work the argument b has to have a property named s which contains a string, otherwise different compilation will lead to different register usage and the bug will not be triggered. To get an arbitrary read/write it is possible to force a type confusion of an object with inline properties and a Float64Array. With that the backing storage pointer of the Float64Array can be overwritten with an arbitrary address by assigning to the inline property of the object. For RCE, a DOM object with a vtable is then corrupted and a virtual function called on it. From there a small ROP chain is triggered which loads the shellcode and jumps into it.

Exploit



*** This is a Security Bloggers Network syndicated blog from SecuriTeam Blogs authored by SSD / Ori Nimron. Read the original post at: https://blogs.securiteam.com/index.php/archives/3765