v8漏洞解析过程

#v8解析过程**

首先,v8解析执行JavaScript语句的基本流程:v8在读取js语句后,首先将这一条 语句解析为语法树,然后通过解释器将语法树变为中间语言的Bytecode字节码,最 后利用内部虚拟机将字节码转换为机器码来执行。

为了加快解析过程,v8会记录下某条语法树的执行次数,当v8发现某条语法树执行 次数超过一定阀值后,就会将这段语法树直接转换为机器码。后续再调用这条js语 句时,v8会直接调用这条语法树对应的机器码,而不用再转换为ByteCode字节码 (也就是V8 中 JIT 优化过程 )

性能速度优化之后带来的一个问题就是假如一段代码被优化之后显示的机器码为 add eax,ebx 等同于a+b,但是攻击者把传入的参数修改为其他类型,而JIT 引擎没 有识别出类型的改变,从而造成类型混淆,可能返回的不是a+b的值,而是内存地 址

#v8对象

以下面这个代码为例:

var b = [1.1, 2.2 , 3.3]

一个对象在内存中布局大致如下所示:

1.jpg

其中elements也是一个对象,它时指明对象中数据的分布位置,这些元素再内存中的分布正好位于数组对象的上方,注意,其他类型可能有些差异,但是大致差不多

2.jpg

v8在实现对象存储时有一套相对复杂的策略机制,并没有完全采用字典的存储方式 (字典是非线性的数据结构,查询效率会低于线性的数据结构)。

3.jpg

枚举下面这个函数中所有的属性在v8中的打印结果

4.jpg

5.jpg

数字属性应该按照索引值大小升序排列,字符串属性根据创建时的顺序升序排列。

在这里我们把对象中的数字属性称为排序属性,在 V8 中被称为 elements;字符 串属性就被称为常规属性,在 V8 中被称为 properties。

至于v8的存储策略是将部分常规属性直接存储到对象本身,我们把这称为对象内属性(in-object properties)通常,我们对象内的属性称之为“快属性”

6.jpg

但是,如果对象属性过多的话,就会采用一个“慢属性”策略:所有的属性元信息 不再是线性存储的,而是直接保存在属性字典中,也就是说element或者 properties不再是线性结构,而是字典结构。

7.jpg

#漏洞分析

漏洞的问题在于src/compiler/js-operator.cc:625处对JSCreateObject操作的表 示存在判断错误,代码如下:

V(CreateObject, Operator::kNoWrite, 1, 1)

Create_Object生成的类型被标识为kNoWrite,kNoWrite标识表示生成的对象不会对内 存做出改变,所以在后面的检测中不会对标识有kNoWrite的对象进行检测。

ObjectCreate()会利用原有Object中的Map生成新的Map,再根据Map的类型,去生 成新的Object,简单来说就是V8 对JS 对象的访问模式的改变。

8.jpg

9.jpg

访问类型由原本的fast变为了dictionary

ObjectCreate()会把一个Object全部的属性值都放到properties中存储,并将原先 的线性结构改成字典结构,当执行了ObjectCreate()之后,v8内部的JIT 在生成 IR-code时每次都是需要做类型检查的,但是由于上面说的create_object会把标识 设置为knowrite,导致跳过检测,代码依旧按照之前的fast 的偏移来访问,从而 造成了下方的内存泄漏。

10.jpg

11.jpg

当我们执行上面这个代码时,当b的某次返回值不是我们所预期的0x5678 时

img

其中的5719是因为,代码在最初运行的时候不会进行优化,当代码反复执行到一定程度时,v8内部的优化机制才会被触发,(我们这里时5719次时触发优化)到这里我们就能触发漏洞了

提示.png

漏洞利用

我们在上一步知道在objectcreate之后访问方式变为Dictionary,而且在 objectcreate操作前后,内存也发生改变。

 a.x1=1 a.x2=2 a.x3=3 a.x4=4 a.x5=5 a.x6=6

12.jpg

可以看到,我们在之后之后访问obj.x6时,实际上访问的是obj.x2的值,假如我们在 obj.x2的位置上放置一个对象的话,那么我们返回的就是这个对象的地址了。

所以说,我们需要找到一个类似于上面这种访问x6 返回x2 值的键值对,一般情 况下,我们可以在createobject之后遍历整个对象的属性和值,返回的条件就是和上面所说的一样。

找到了相应的键值对 之后比如向上面的x6 & x2 键值对之后,我们把x2 的值设置为 一个arraybuffer对象,

a.x2 = ArrayBufferObject

因此,根据上面的原理,当我们访问x6 时,本来我们得到的应该是一个数字,但是实际 上我们得到的是一个ArrayBuffer 的地址。

ArrayBuffer也是一种对象,它里面的backing_store 可以指向一片可读可写的数 据流空间,大概的结构如图所示

13.jpg

我们可以看到,和普通的对象类型相比的话,backing_store 的位置相当于是普通对象里的第二个对象内属性值,所以,我们可以在触发漏洞的时候,把backing_store 的值给修改了,让他指向另外一个ArrayBuffer。

简单的来说,我们再次利用漏洞,返回了ArrayBuffer 1的地址,由于系统认定他是一个数字,我们可以修改它的值,所以,我们把刚刚得到的ArrayBuffer 2 的地址写道ArrayBuffer 1 中覆盖掉原来backing_store 指向的地方。

14.jpg

这个时候,我们对可以将backing_store 指向任意想要设置的地址,而我们对 ArrayBuffer 2 的操作,都是对那个地址的任意读写操作了

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇