作者:启明星辰ADLab
原文链接:https://mp.weixin.qq.com/s/yeu9IZSNrp1f_lK5oIdL9A
4月13日,国外安全研究人员在社交媒体上发布了Chrome 的0Day 漏洞[ ],漏洞编号为CVE-2021-21220,并在github上公开了该漏洞的POC以及利用代码,相关的利用代码在关闭沙盒的情况下可达到远程代码执行。由于chromium 相关框架的广泛应用,该漏洞在其他浏览器或脚本引擎中仍有存在的可能。该漏洞在chrome 90.0.4430.72版本已经修复,提醒广大用户及时更新到最新版本[ ],以规避该漏洞存在的攻击风险。
启明星辰ADLab分析发现,该漏洞存在于Chrome 的JavaScript 解析引擎V8中,POC主要代码如下:
在POC line4执行异或操作,(2**31)^0=-2147483648。根据ECMA标准[ ],异或的结果是32位整数:
在v8 SimplifiedLowering阶段,增加了对异或的结果执行ChangeInt32ToInt64的操作:
SimplifiedLowering 执行后,异或的类型被标记为Word32:
在MachineOperatorOptimizer阶段,由于是和0做异或,所以用左操作数代替异或操作。
此时的结构图如下,可以看出异或的结果是Word32|TypeUint32:
在指令选择时,对于VisitChangeInt32ToInt64操作,根据其输入类型选择操作码:
所以,这里的操作码是kX64Movl操作码,该指令在将源操作数移至目的位置时并不做符号扩展,这样在POC line4中x的值为2147483649,于是在poc line12的位置,编译器其实使用的是x=1的值作为创建数组的长度。这是编译器未曾预料到的情况。
在变量的范围分析中,编译器认为创建的数组长度是0:
在执行POP时,会先判断数组的长度是否为0,如果不是就会将其长度减1:
由于数组长度固定,编译器在LoadElimination 的过程中会进行常量折叠,在代码路径走到这里的时候通过StoreField操作将数组的长度直接赋值为-1:
由于是smi,所以是0xfffffffe:
打印数组长度:
这时超长的数组就出炉了,任由你玩了。从补丁对比上来看[ ],对于ChangeInt32ToInt64将其输入作为有符号对待,这样就避免了该漏洞通过该路径触发。
关于利用的部分,基本是老套路,不再赘述。
参考链接:
[1] https://twitter.com/r4j0x00/status/1381643526010597380
[2] https://www.google.com/chrome/
[3] https://www.ecma-international.org/publications-and-standards/standards/ecma-262/
[4] https://chromium-review.googlesource.com/c/v8/v8/+/2820971/3/src/compiler/backend/x64/instruction-selector-x64.cc#1379
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1563/