2020-11-18 14:36:309982人阅读
研究人员在分析CVE-2020-1380 IE 0 day漏洞的根源时发现了另一个触发类似的UAF漏洞的方法。该漏洞CVE编号为CVE-2020-17053,微软已在11月的补丁日修复了该漏洞。
将Item设置为TypedArray
在CVE-2020-1380漏洞的PoC中,代码段中有“arr[0] = value1”,这些JIT代码生成的代码会通过调用覆写的valueOf 回调函数来触发UAF漏洞:
图 1. CVE-2020-1380PoC部分
JIT 引擎会执行操作将item 设置为TypedArray。那么在jscript9.dll中不在JIT中设置item为TypedArray会怎么样呢?
如果设置为TypedArray的item不在JIT中执行,jscript9.dll会在翻译器中使用下面的代码:
图 2. Js::TypedArray
该函数有4个步骤:
· 首次调用函数Js::JavascriptConversion::ToNumber()
· 检查TypedArray的ArrayBuffer是否是独立的
· 比较TypedArray的长度和设置的元素的索引
· 第二次调用函数Js::JavascriptConversion::ToNumber(),并设置值为ArrayBuffer
研究人员很好奇为什么要调用Js::JavascriptConversion::ToNumber() 函数两次。答案可能是第一次调用是用户代码的回调函数。攻击者利用回调函数来释放TypedArray的 ArrayBuffer并获取UAF漏洞。然后检查TypedArray的 ArrayBuffer是否是独立的,这是必要的检查并预防ArrayBuffer的内存在用户代码回调中释放。
检查后,会第二次调用该函数,这会保存会话结果到ArrayBuffer中。图3是代码执行流:
图 3. Js::TypedArray
这就是问题所在。代码只检查了第一次调用,但没有对第二次调用进行检查。
图 4. 可能的问题
PoC
CVE-2020-17053漏洞的PoC如图 5所示:
图 5. CVE-2020-17053 PoC
以下步骤可以触发该漏洞:
· 函数pwn用来设置item 为指定的TypedArray索引元素;
· 对象obj有一个覆写的valueOf 回调函数,该函数用来释放ArrayBuffer,与CVE-2020-1380 漏洞类似;
· 调用函数pwn 和设置第二个参数obj,当代码'arr[index] = value'[EC(1] 指定时,函数Js::JavascriptConversion::ToNumber() 就会被调用,valueOf 回调函数会被调用两次;
· 第一次valueOf 回调函数中,因为变量flag 是0,因此关于 ArrayBuffer的操作并不会被执行。第一次valueOf 回调函数执行后,flag 会被设置为1;
· 第二次valueOf 回调函数中,因为变量flag 是1,所以关于 ArrayBuffer的操作会被执行,会引发UAF漏洞。
最后因为ArrayBuffer 内存被释放,会引发UAF 漏洞。所有类型的TypedArray 都可以触发该漏洞,但都在11月发布的补丁中修复了。
图 6. 奔溃截图
漏洞利用分析
因为释放的ArrayBuffer的受控制的内存大小,UAF 漏洞很容易就可以利用,具体步骤如下:
1. 通过创建许多JS 数组对象来用LargeHeapBlock来占用释放的内存;
2. 使用valueOf 回调函数的返回值来设置LargeHeapBlock的 allocCount为 0;
3. 回调函数CollectGarbage() 会释放LargeHeapBlock 对象,其中allocCount 被设置为0,这会导致第二个在IE 定制堆中获取UAF;
4. 再次创建许多JS 数组对象,利用第二个UAF漏洞利用的可能性来使两个JS数组指向相同的缓存;
5. 使用两个JS 数组来实现读写原语,最后实现代码执行。
本文翻译自:https://www.trendmicro.com/en_us/research/20/k/cve-2020-17053-use-after-free-ie-vulnerability.html