专栏名称: 深信服千里目安全实验室
深信服科技旗下安全实验室,致力于网络安全攻防技术的研究和积累,深度洞察未知网络安全威胁,解读前沿安全技术。
目录
相关文章推荐
清晨朗读会  ·  渊源直播 ·  2 天前  
清晨朗读会  ·  清晨朗读3180:When Your ... ·  2 天前  
进出口银行  ·  坚定信心 深化改革 ... ·  12 小时前  
银行家杂志  ·  一银行获批筹建! ·  2 天前  
清晨朗读会  ·  渊源直播 ·  4 天前  
51好读  ›  专栏  ›  深信服千里目安全实验室

Chromium issue 1196683、1195777分析

深信服千里目安全实验室  · 公众号  ·  · 2021-04-20 19:28

正文

漏洞概述


2021年4月12日,开源浏览器内核Chromium的一处改动提交[1]引起了关注。这是Chromium Javascript引擎v8的一处漏洞bugfix。同时针对该bugfix的回归测试样本regress-1196683.js也被提交。基于该回归测试,有安全研究员公布了完整的利用代码。由于Chromium开发流程,该漏洞于4月13日Chrome的release版中才被修复[2]。


无独有偶,4月15日Chromium代码仓库另一处改动提交[3]也包含了回归测试样本regress-1195777.js。基于该样本,完整的利用代码再次被公布。由于最新的Chrome release版没有引入该bugfix,利用代码仍可以在最新的Chrome浏览器的渲染进程稳定利用。当受影响版本的Chormium内核浏览器在没有开启沙箱的情况下(--no-sandbox),访问攻击者构造的恶意链接时,将会触发该漏洞,造成远程代码执行。


漏洞分析


1 Issue 1196683原理分析

该issue的bugfix代码如下:

bugfix修复了v8 TurboFan在指令选择阶段针对ChangeInt32ToInt64节点的指令选择错误问题。改动前根据ChangeInt32ToInt64节点的输入节点类型选择指令。如果输入节点类型为有符号整数,则选择指令X64Movsxlq先做符号扩展,否则选择X64Movl做零扩展。Bugfix则无论输入类型,一律选择X64Movsxlq做符号扩展。根据修复代码可以猜测,这里应该是ChangeInt32ToInt64节点输入类型为无符号整数,导致指令选择阶段错误选择X64Movl指令引发的安全问题。


首先通过regress-1196683.js分析漏洞根因:

触发JIT的foo函数只有一行代码,重点关注 (arr[0] ^ 0) + 1在TurboFan中关键阶段的优化过程:


  • TyperPhase

异或操作符对应32节点,其两个输入分别为常量0(24节点)和arr[0](80节点)。


  • SimplifiedLoweringPhase

原32节点SpeculativeNumberBitwiseXor被优化成Word32Xor,并加入后继节点ChangeInt32ToInt64。此时ChangeInt32ToInt64节点的输入节点Word32Xor类型为Signed32。


  • EarlyOptimizationPhase

可以看到原32节点被删除,并用80节点替代作为110节点ChangeInt32ToInt64的输入。此时ChangeInt32ToInt64节点的输入节点LoadTypedElement类型为Unsigned32。


这段逻辑对应的v8代码如下:

如上所示,对于x ^ 0 => x的情况,使用左节点替换当前节点,从而引入了错误的数据类型。


  • InstructionSelectionPhase

根据前面的分析,指令选择阶段,ChangeInt32ToInt64节点的输入节点LoadTypedElement类型为Unsigned32,最终选择X64Movl指令替换ChangeInt32ToInt64节点:

因为错误选择了零扩展指令X64Movl,导致(arr[0] ^ 0)返回错误的值:0x0000000080000000。


最终利用该漏洞,通过如下代码可以得到一个JIT中非预期值为1的变量x(预期值应为0):


2 Issue 1195777原理分析

该issue的bugfix代码如下:

bugfix修复了v8 TurboFan在SimplifiedLowering阶段,对64位整数转为32位整数的数据类型转换节点生成错误的问题。改动前对于当前节点的输出类型为Signed32或Unsigned32均生成TruncateInt64ToInt32节点(截断);改动后,对于当前节点的输出类型为Unsigned32的情况,还需要检查use_info的类型,只有在use_info.type_check() == TypeCheckKind::kNone的情况下,才会生成TruncateInt64ToInt32节点。


首先通过regress- 1195777.js分析漏洞根因:

触发JIT的foo函数中关键代码为return -1 < Math.max(0, x, -1)。重点关注 Math.max(0, x, -1)在TurboFan中关键阶段的优化过程:


  • TyperPhase

Math.max(0, x, -1)对应了56,58节点,58节点输出作为41节点SpeculativeNumberLessThan(


  • TypedLoweringPhase

Math.max(0, x, -1)两个常量参数0,-1(54,55节点)被替换成了常量节点32和14。


  • SimplifiedLoweringPhase

原56,58的NumberMax节点,被Int64LessThan + Select节点替换;原41节点SpeculativeNumberLessThan被替换为Int32LessThan。在处理SpeculativeNumberLessThan输入节点的时候,因为输入节点(Select)的输出类型为Unsigned32,从而触发漏洞,导致76节点TruncateInt64ToInt32被错误生成。从而将Math.max(0, x, -1)的结果截断为Signed32。因此,当Math.max(0, x, -1)中的x为Unsigned32时,会被TruncateInt64ToInt32错误截断为Signed32。


最终利用该漏洞,通过如下代码可以得到一个JIT中非预期值为1的变量x(预期值应为0):


3 漏洞利用分析

根据上面对这两个漏洞的分析可以知道:这两个漏洞是TurboFan在做整型数据类型转换(扩展、截断)时发生的错误。利用这两个漏洞,通过如下代码可以得到一个JIT中非预期值为1的变量x。接下来根据在野利用样本[4][5],分析如何根据这个错误数值为1的变量x,实现远程代码执行。


具体利用步骤为:

  • 借助这个错误数值为1的变量x,构造一个长度为1的Array;

  • 通过Array.prototype.shift()获得一个长度为0xFFFFFFFF的越界数组;


关键代码如下:

其中var arr = new Array(x);对应的JIT代码:

这里rdi为数组的长度,即x的值1。指针压缩后,左移一位(rdi+rdi),存放在JSArray.length属性(+0xC)。


arr.shift();对应的JIT代码:

这里可以看到,arr.shift()后,数组的长度直接由常量0xFFFFFFFE赋值,其优化过程:


(1)TyperPhase

这里数组长度赋值操作主要由152,153节点组成。其中152节点做Array.length-1计算操作。153节点将计算结果保存在Array.length(+0xC)处。


(2)LoadEliminationPhase

这里可以看到,由于在Ignition执行过程中收集的x值为0,这里做了常量折叠(0-1=-1),从而得到常量0xFFFFFFFF。左移一位后为0xFFFFFFFE,存放在Array.length(+0xC)处。从而得到一个长度为0xFFFFFFFF的越界数组。


得到越界数组后,后面的利用方法就比较通用了,一般为:

  • 借助这个越界数组,实现addrof/fakeobj

  • 借助addrof/fakeobj,伪造一个JSArray,实现任意地址读写


样本中利用arr和cor实现任意地址读写的内存布局为:

(1)首先利用漏洞获得一个长度为0xFFFFFFFF的arr(红框)

(2)利用越界的arr和cor实现addrof/fakeobj(绿框)

(3)利用越界的arr修改cor的长度(黄框)

(4)利用越界的cor,泄露cor的map和properties属性(蓝框),构造一个fake JSArray,借助这个fake JSArray实现任意地址读写


  • 借助WebAssembly执行shellcode

最后借助WebAssembly创建一个RWX属性的内存页,拷贝shellcode至该内存页,执行shellcode。


完整的利用演示:


4 结论

经分析,这两个v8 JIT的漏洞触发容易且利用简单,在没有开启沙箱的Chromium内核浏览器中可以稳定利用。考虑到这两个漏洞只是Chromium内核浏览器渲染进程的远程代码执行漏洞,无法穿透浏览器沙箱(默认开启),建议用户不要关闭Chromium内核浏览器的沙箱,且不要点击不明链接。








请到「今天看啥」查看全文


推荐文章
清晨朗读会  ·  渊源直播
2 天前
清晨朗读会  ·  清晨朗读3180:When Your Mind Can't Let Go (3)
2 天前
银行家杂志  ·  一银行获批筹建!
2 天前
清晨朗读会  ·  渊源直播
4 天前
新浪广东  ·  为什么女人的寿命比男人长?
7 年前
香港凤凰周刊  ·  随便摸 不要钱
7 年前