【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息

简述:

微软于2020年5月12日发布了一项安全更新,该补丁修补了CVE-2020-1062漏洞,该漏洞是针对IE浏览器旧版脚本引擎jscript.dl的UAF(use-after-free)漏洞。该漏洞可造成远程代码执行,攻击者利用此漏洞可获得与当前用户相同的权限。下面我们将结合poc与官方补丁对该漏洞进行深入的分析。

 

POC分析:

图片[1]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

 

定位异常:

使用windbg调试开启页面堆的IE进程,加载POC,捕获程序异常,问题出现在jscript.dll的JsArrayPush函数中,对应js代码中的push操作。

图片[2]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

根据mozilla的描述:

[].push.call(this,elem):push()方法用于将一个或多个元素添加到数组的末尾,并返回该数组的新长度,该方法被特意设计为通用的,结合call方法,可使[].push认为处理对象为数组,并在一个对象上正常工作。

 

JsArrayPush分析:

图片[3]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

通过分析发现漏洞在JsArrayPush函数中的逻辑为:

  1. 获取this对象的相关属性;
  2. 判断长度属性是否为int类型(否);
  3. 对长度属性进行类型转换(该过程触发toString回调,并执行wirte释放内存);
  4. 使用已经被释放的指针,程序崩溃。

 

获取对象”length”属性:

Jscript引擎通过向NameTbl::GetVal函数传递sym参数,获取目标对象的属性。

在此处,我们通过GetVal获取”this”对象的”length”属性,函数返回时将其存储在ebp-4Ch的变量中。

图片[4]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

程序继续执行,到如图所示位置时对“length”属性进行类型判断,判断结果会决定是否跳过类型转换步骤,即ConvertToScalar的函数调用,该函数会触发目标toString回调。

图片[5]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

关于toString的回调,可以通过对cos函数下断验证:

图片[6]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

详细跟踪判断过程,读取ebp-4Ch处对象的vt值,根据官方文档,当该值为3时表示”length”属性为4字节有符号整型,则跳过类型转换过程。

这里通过prototype为布尔原型类添加了”length”属性,使其对应vt值为0x80,从而进入类型转换流程。

图片[7]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

程序继续执行,来到ConvertToScalar函数,该函数暂未调用,可以看到ebp-20h处为一个虚表指针,在单步步过ConvertToScalar后,可以看到该虚表指针已被释放。

图片[8]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科图片[9]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

继续运行,程序尝试调用ebp-20h处的虚表指针时,触发异常,造成UAF漏洞。

图片[10]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

 

深入分析:

POC运行过程中ConvertToScalar函数的执行流程如下图所示,可以看到进入类型转换流程后,程序对传入变量的vt值进行判断,当其为0x87时调用到InvokeDispatchEx函数。经过修改POC测试,我们发现仅有当toString回调重写在父窗口时,即”length”对象与其toString回调分别定义在父窗口与子窗口两个线程中时,才会触发该流程(反之,传入变量的vt值为0x81将调用NameTbl::InvokeInternal)。

图片[11]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

为了获取重写的toString回调方法,引擎使用与获取”length”属性时同样的方法,向NameTbl::GetVal函数传递sym参数,通过设置内存访问断点可以看到该过程。

图片[12]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

图片[13]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

通过对NameTbl::GetVal函数下断并查看其第一个参数,我们发现该过程在触发toString回调之前,会先进行valueOf回调,通过修改POC将toString改为valueOf同样会造成异常。

图片[14]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

程序继续运行,执行到cos函数,说明此时已经进入toString内部,并准备运行document.write操作,达到释放的目的。

图片[15]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

此时依然存在一个疑点,若没有将”length”对象和toString回调分别定义在两个窗口中,document.wirte完成时也不能成功释放,那么为什么一定要通过父窗口定义toString的方式才能成功完成释放呢?这里猜测是引擎的垃圾回收机制所使用的标记-清除算法出现了问题,我们将在补丁对比中寻求答案。

补丁对比:

使用bindiff对补丁前后的jscript.dll进行对比,(左)补丁后版本为KB4556798 (IE 11.0.190) ;(右) 补丁前版本为KB4550905 (IE 11.0.185) 。

通过补丁前后的函数相似度对比,可以看出补丁的主要修改内容为CSession::Close和CSession::~CSession两个函数,且改动程度比我们预想的要小很多,这对我们的分析非常有利。

图片[16]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

在CSession::Close函数中,主要的逻辑块没有发生变化,仔细对比发现图中所示位置删除了IScavengerBase::UnlinkFromGc调用。

图片[17]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

而在CSession::~CSession即析构函数中添加了IScavengerBase::UnlinkFromGc调用。

图片[18]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科可以明显发现,补丁修改的逻辑仅仅是更改了UnlinkFromGc的调用位置,这符合我们之前的猜测,接下来对其进行验证。

在CSession::Close函数设置断点后,查看栈回溯时发现了document.write和push操作。说明在使用document.write操作清空子窗口文档时,确实会调用到补丁修改的close函数。

图片[19]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科调试未打补丁的IE进程,在Close函数调用UnlinkFromGc前断下,手动修改eip的值,将目标指令跳过,继续运行将不再触发异常,且在手动关闭窗口前未发现CSession::~CSession的调用,符合我们的分析与预测。说明补丁通过修正UnlinkFromGc操作的调用时机,从而避免子窗口资源的提早释放,修复了该UAF漏洞。

图片[20]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

官方通告:

https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1062

参考链接:

https://www.accenture.com/us-en/blogs/cyber-defense/exploitation-case-study-cve-2020-1062-vulnerability-in-ie11

https://github.com/Accenture/AARO-Bugs/tree/d4c44eb5d686a1e9f1386912bb2a58cb77ccb51e

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

 

文章出自:安洵信息星际实验室

更多信息请关注:

公众号:安洵信息图片[21]-【漏洞分析】 | CVE-2020-1062漏洞分析 – 作者:安洵信息-安全小百科

来源:freebuf.com 2020-08-03 16:45:43 by: 安洵信息

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论