标题要吓人,才有人来!
紧跟着前面:
https://bbs.pediy.com/thread-267529.htm
环境:
Ubuntu 18.04
turbofan 图表都是在 release的v8下产生的
命令./d8 poc.js --allow-natives-syntax --trace-turbo
1.1:在v8执行时,在poc.js后面加上--trace-turbo执行参数,会产生turbofan(优化过程各个阶段的处理逻辑)图表。
1.2:分析turbofan的图表时,最重要的是找到第一个出现错误的地方。v8 优化的漏洞有一点不同于一般的溢出类或UAF类漏洞的地方是,漏洞的直接原因通常很难在调试器中直接体现出来。在传统的溢出和UAF中,我们经常可以制造一个崩溃,来体现漏洞发生的直接原因,而调试v8优化类漏洞POC的时候,经常给人一种,怎么地,就溢出了的感觉。究其原因,个人感觉比较合理的解释是其漏洞出现的根源往往是在v8工程师自己设计的逻辑层面。
1.2:0xFFFFFFFF是个什么?或者说v8会把他当作什么?
首先我们可以简单排除v8把他当成int64或unsigned int64的可能性。(这样会造成资源上的浪费),可能的解释为一个int32数字或一个unsigned int 32数字。如果解释为int32类型,那么我们打印就会输出-1,如果解释为unsigned int 类型,那么我们打印就会为4294967295。那到底v8会将其解释为什么类型呢,我们可以写个简单的代码验证一下:
var x=0xFFFFFFFF
console.log(x);
图1.1.1
显然v8把0xFFFFFFFF当成了unsigned int32 的类型。换一句话说v8把0xFFFFFFFF当成unsigned int32才是其规定的合法操作,如果当成了int32类型,则会出现前后不一致的情况,导致结果出现错误。
这里写的有点啰嗦,主要是这点对理解这个漏洞原因还挺重要。
1.3:v8优化的过程中往往会会对计算的结果进行预估,进而对结果形成一个范围,而预估的范围本身,会影响到后面优化的过程,我们分析优化的漏洞通常就是分析其预估的范围是否有误,以及对后面优化过程的影响。
这点有点像那种综艺节目,第一个人看到一个东西,然后口述给第二个人听,然后第二个人口述给第三个人听,以此信息传递下去,中间有一个人理解错误的话,就会导致后面全部人理解错误。
原始的poc1.js
分别输出的是:
图2.1.1
这里可以看到经过优化后,参数x=0xFFFFFFFF的情况下,-1<Math.max(0,x,-1)的结果为false 。和优化之前的结果不一样!
这里把poc1.js调整下,以下将其称为poc2.js:
图 2.1.2
从图2.1.2可以看到,v8对Math.max(0,x,-1)优化前后计算的值 都是一样 ,那为什么前面poc1.js经v8优化后的-1<Math.max(0,x,-1)会返回false呢?
我们可以推测经过v8的优化,在poc1.js在运算完Math.max(0,x,-1)之后,对其结果0xFFFFFFFF(4294967295)的解释出现了问题,原本应该解释为unsigned int32 类型的,被错误的解释为int32类型。0xFFFFFFFF这个数如果解释为int32的话,结果就会为-1,这样的话-1<-1,最终结果自然就会变为false。
关于v8 turbofan图表分析这一块本人也是新手,看别人写的都是直接看几个重要的阶段,本人不是太懂,就用笨一点的方法,把每个图相关过程都看一下 。
第一个看到有对结果进行范围判断的是:
2.2.1:V8.TFTypedLowering 57
图 2.2.1
图2.2.1可以看出
a):这一阶段的优化初始化过程为节点 1 3 和节点 19 合并然后通过20节点 Phi[kRepTagged] 运算后,结果为Range(-1, 4294967295) 。
b): 这一阶段的优化是将poc.js中的Math.max(0,x,-1)拆分为两个NumberMax, 将初始化数值分别与节点 31 的常数0和节点 13 的常数-1运算。
这里并未看出存在什么问题。
2.2.2:V8.TFLoopPeeling57
图 2.2.2
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-8-5 10:31
被苏啊树编辑
,原因: