启明星辰ADLab:Chrome 任意代码执行漏洞分析
发布时间 2021-04-164月13日,国外安全研究人员在社交媒体上发布了Chrome 的0Day 漏洞(参见参考链接[1]),漏洞编号为CVE-2021-21220,并在github上公开了该漏洞的POC以及利用代码,相关的利用代码在关闭沙盒的情况下可达到远程代码执行。由于chromium 相关框架的广泛应用,该漏洞在其他浏览器或脚本引擎中仍有存在的可能。该漏洞在chrome 90.0.4430.72版本已经修复,提醒广大用户及时更新到最新版本(参见参考链接[2]),以规避该漏洞存在的攻击风险。
启明星辰ADLab分析发现,该漏洞存在于Chrome 的JavaScript 解析引擎V8中,POC主要代码如下:
在POC line4执行异或操作,(2**31)^0=-2147483648。根据ECMA标准(参见参考链接[3]),异或的结果是32位整数:
在v8 SimplifiedLowering阶段,增加了对异或的结果执行ChangeInt32ToInt64的操作:
SimplifiedLowering 执行后,异或的类型被标记为Word32:
在MachineOperatorOptimizer阶段,由于是和0做异或,所以用左操作数代替异或操作。
此时的结构图如下,可以看出异或的结果是Word32|TypeUint32:
在指令选择时,对于VisitChangeInt32ToInt64操作,根据其输入类型选择操作码:
所以,这里的操作码是kX64Movl操作码,该指令在将源操作数移至目的位置时并不做符号扩展,这样在POCline4中x的值为2147483649,于是在poc line12的位置,编译器其实使用的是x=1的值作为创建数组的长度。这是编译器未曾预料到的情况。
在变量的范围分析中,编译器认为创建的数组长度是0:
在执行POP时,会先判断数组的长度是否为0,如果不是就会将其长度减1:
由于数组长度固定,编译器在LoadElimination 的过程中会进行常量折叠,在代码路径走到这里的时候通过StoreField操作将数组的长度直接赋值为-1:
由于是smi,所以是0xfffffffe:
打印数组长度:
这时超长的数组就出炉了,任由你玩了。从补丁对比上来看(参见参考链接[4]),对于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
启明星辰积极防御实验室(ADLab)
ADLab成立于1999年,是中国安全行业最早成立的攻防技术研究实验室之一,微软MAPP计划核心成员,“黑雀攻击”概念首推者。截止目前,ADLab已通过CVE累计发布安全漏洞近1100个,通过 CNVD/CNNVD累计发布安全漏洞1000余个,持续保持国际网络安全领域一流水准。实验室研究方向涵盖操作系统与应用系统安全研究、智能终端安全研究、物联网智能设备安全研究、Web安全研究、工控系统安全研究、云安全研究。研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。