In my previous blog titled CVE-2020-1380: Analysis of Recently Fixed IE Zero-Day, I discussed how that vulnerability was caused by a type inference error in the browser’s JIT engine, which can be exploited by neutering ArrayBuffer and resulted in a use-after-free (UAF) vulnerability. While analyzing the root cause of this vulnerability, I found another path to trigger a similar UAF vulnerability by neutering ArrayBuffer — but this time, without the need for the JIT engine. This bug was submitted to Microsoft in September via the Zero-Day Initiative and fixed in November’s Patch Tuesday as CVE-2020-17053. In this blog, I will attempt to explain this new vulnerability.
Set Item to TypedArray
Recall that in the proof-of-concept code of CVE-2020-1380, the code snippet “arr = value1,” which is generated by JITed code will trigger a UAF bug by invoking an overridden valueOf callback function:
The JIT engine executes the operation of setting an item to TypedArray. What about setting an item to TypedArray without the JIT in jscript9.dll?
If setting an item to TypedArray is not executed in JIT, jscript9.dll uses the following code snippet in Interpreter:
This function has four major steps:
- Check if TypedArray's ArrayBuffer is detached
- Compare the index of setting element with TypedArray's length
After the check, it calls the conversion function again, which will save the conversion result to ArrayBuffer. Figure 3 shows the aforementioned code execution flow:
Now we can see what the protentional problem is. The code only checks the first conversion call, but what about the second conversion call? Is it possible for the user-defined callback function to have a different code execution flow in each callback?
Neutering ArrayBuffer Without JIT
The proof of concept of CVE-2020-17053 is shown in Figure 5:
The following steps can trigger this bug:
- Function pwn is used to set the item to a specified index element of TypedArray
- Object obj has an overridden valueOf callback function, which is used to free ArrayBuffer by Worker, like CVE-2020-1380
- In the first valueOf callback, the operation of neutering ArrayBuffer will not be executed because the variable “flag” is 0. At the end of the first valueOf callback, the flag is set to 1
At last, we get a freed memory of ArrayBuffer, which leads to a UAF vulnerability. All kinds of TypedArray can trigger this bug, but they all have been fixed in the November patch.
Because of the controllable memory size of the freed ArrayBuffer, this UAF vulnerability is easy to exploit using the following steps:
- Set LargeHeapBlock's allocCount to 0 using the valueOf callback function return value
- Call function CollectGarbage() manually to free the LargeHeapBlock object, which allocCount has set to 0; this will result in a second chance to get UAF in the IE custom heap
By analyzing the exploits of CVE-2020-1380 in the wild, we can speculate that attackers are choosing to target jscript9.dll instead of vbscript.dll or jscript.dll, as they did in the past. In this blog, I explained how I found another similar UAF vulnerability that does not use the JIT engine through simple reverse engineering. The security issues surrounding jscript9.dll may not be over.
- 1010602 - Microsoft Internet Explorer Memory Corruption Vulnerability (CVE-2020-17053)
Trend Micro™ TippingPoint™ protects users from exploits that target this via the following rule:
- 38412: HTTP: Microsoft Internet Explorer Worker Use-After-Free Vulnerability (CVE-2020-17053)