安全路透社
当前位置:安全路透社 > 网络转载 > 正文

CVE-2015-8651漏洞原理再度分析

*本文原创作者elli0tn0phacker,属于原创奖励计划,禁止转载。

0×00 调试环境

OS: win7 x86
IE: ie10
Flash: flashplayer18_0r0_209_win_debug

0×01 背景

之前在Freebuf看到一篇安天追影发表的文章:《暗黑客栈CVE-2015-8651漏洞原理分析》(http://www.freebuf.com/articles/network/93516.html),文中有对CVE-2015-8651漏洞原理的详细分析。苦于无法拿到文章中的样本,且个人水平有限,不能根据文章理解其漏洞原理。特别是漏洞触发关键代码描述略简:

israbye FreeBuf.COM

红框处的文字让我苦思冥想,构造多种POC,均无法复现漏洞现场。好在最近拿到的某EK样本中有该CVE,方才了解其漏洞原理。

0×02 漏洞原理

DomainMemory以及li*/si*等方法的使用不再详述,可以参考安天的那篇文章。需要注意的是li*/si*等方法均由as3 code实现,而不是native code,运行后会由avm2生成jited code。

以li32函数为例,观察正常情况下生成的jited code的逻辑。poc代码:

israbye FreeBuf.COM

poc首先初始化ba,并赋值给domainMemory。关键部分在test_li32方法中,调用了两次li32,传入的参数分别为_loc3_=1+this.add(param1)和_loc3_=_loc3_-0×1000,test_li32方法jited后的代码如下:

israbye FreeBuf.COM

说明:

1)1处对应poc中this.add(param1)的调用,因为是第一次调用add方法,call eax进入verifyjit流程,后面如果再次调用add方法则会直接调用add方法对应的jited code;

2)2处对应poc中_loc3_ = 1 + this.add(param1); _loc4_ =li32(_loc3_)的流程,li32方法会对输入参数进行长度校验,因为是从当前地址开始往后读4Bytes,需要对domainMemory的长度-4后再进行比较,详细分析如下:

israbye FreeBuf.COM

3)3处对应poc中:_loc3_ = _loc3_ – 0×1000; _loc2_ =li32(_loc3_);其中li32返回值赋给_loc2_,因为只是局部变量后续并未使用,jited code优化后没有2)校验后的赋值操作,其余与2)同理。

综上分析,li32会对输入进行长度校验,具体做法就是取domainMemory长度-4,和输入进行比较,如果输入的数据> domainMemory长度-4,则抛出异常,不再读取domainMemory里的数据。

现在对poc代码稍作修改,修改点只有一处,将_loc3_ =1 + this.add(param1);修改为_loc3_ = 0x7FFFFFFC +this.add(param1);

israbye FreeBuf.COM

再来观察生成的Jited code:

israbye FreeBuf.COM

这里发现修改过的poc在jit后li32的校验被优化成了一个,并且校验的是第二个li32方法!也就是说我们利用这个漏洞可以通过第一个li32越界读取domainMemory以外的数据,只要保证越界的地址-0×1000能够通过第二个li32的校验即可。于是就有了最终的poc:

israbye FreeBuf.COM

这里把add方法里的加数修改为0×80000004,其目的是add方法的返回值 0×80001004+0x7FFFEFFC = 0,从而绕过第二个li32的长度检查,调试过程:

israbye FreeBuf.COM

最终利用漏洞成功读取domainMemory外的内存数据:

israbye FreeBuf.COM

同理si32也存在相同漏洞,利用漏洞可以修改domainMemory外的内存数据。

后面的利用方法一般都是利用HeapSpray排布Vector或者ByteArray对象,通过修改长度属性实现任意地址读写,不再说明。

*本文原创作者elli0tn0phacker,属于原创奖励计划,禁止转载。

未经允许不得转载:安全路透社 » CVE-2015-8651漏洞原理再度分析

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册