从BinDiff到0day 在IE中利用CVE-2019-1208
2019-09-21 07:01:00 Author: xz.aliyun.com(查看原文) 阅读量:209 收藏

本文是翻译文章,原文链接:https://blog.trendmicro.com/trendlabs-security-intelligence/from-bindiff-to-zero-day-a-proof-of-concept-exploiting-cve-2019-1208-in-internet-explorer/

去年六月,我向微软公布了internet Explorer(IE)中的UAF漏洞,它被评为严重等级,并被命名为CVE-2019-1208,接着在微软的9月补丁星期二发表

我通过BinDiff工具发现了这个漏洞,并编写了一个PoC,展示了如何在Windows 10 RS5中利用它

这篇文章对此漏洞进行了更深入的分析,以下是该研究的概述

深入分析:https://documents.trendmicro.com/assets/Tech-Brief-A-Proof-of-Concept-Exploiting-CVE-2019-1208-in-Internet-Explorer.pdf

如上所述,CVE-2019-1208UAF漏洞,这类安全漏洞可以破坏有效数据、引发进程crash、并且可以精心利用最终导致任意代码执行。而对于本文介绍的CVE-2019-1208而言,成功利用此漏洞的攻击者可以获得系统当前用户权限。如果当前用户具有admin权限,则攻击者可以劫持系统——从安装或卸载程序,查看和修改数据 到 创建具有完全权限的用户。

还有一种更有形的攻击情形,攻击者向不知情的用户发送钓鱼邮件,并诱使他们通过IE访问恶意网站(存在CVE-2019-1208的漏洞)。

或者,攻击者可以发送带有附件的垃圾邮件,其中包含该漏洞的exp。这些附件可以是启用了IE渲染引擎的Microsoft Office文档,也可以是嵌入了ActiveX控件的的应用程序,而ActiveX控件又包含exp。

攻击者还可以在一些合法网站上布置攻击代码,例如那些接受用户的输入的网站。

下图为VbsJoin的代码流:

我的研究始于BinDiff,当时我正试图比较vbscript.dll的5月和6月的版本,寻找其中被更改的函数,而这个模块包含VBScript引擎的API函数。最终我发现通过SafeArrayAddRefSafeArrayReleaseDataSafeArrayReleaseDescriptor函数进行了一些修复

然而,受我之前发现的漏洞CVE-2018-8373的启发,进一步分析后我使用VBScriptClass经过下列步骤触发了UAF漏洞:

  1. arr = Array(New MyClass),创建一个SafeArray并在arr[0]处保存VBScriptclass: MyClass

  2. Callback: arr = Array(0)Join(arr)将触发MyClass的回调函数Public Default Property Get。在此回调中,为变量创建了一个新的SafeArray,如下图所示而这个新的SafeArray不受SafeArrayAddRef函数的保护。因此,正常的代码流假设 被这个回调打破

  1. arr(0) = Join(arr),当从Public Default Property Get返回时,VBsJoin中的代码将会调用SafeArrayReleaseDataSafeArrayReleaseDescriptor来减少SafeArrayDataSafeArrayDescriptor的引用计数。但是,新的SafeArray不受SafeArrayAddRef保护,并且SafeArrayDataSafeArrayDescriptor的引用计数为0。

    因此,新的SafeArray的SafeArrayDataSafeArrayDescriptor将在函数SafeArrayReleaseDataSafeArrayReleaseDescriptor被free,如下图所示:

其中,代码快照显示内存中的arr = Array(New MyClass)(顶部),内存中的arr = Array(0)callback位于底部

将VbsJoin的返回值保存到arr(0)时,PoC在vbscript!AccessArray中崩溃(见下图),因为SafeArrayDescriptor被free,Variant arr仍然保存释放的SafeArrayDescriptor的指针。

显示PoC如何在vbscript!AccessArray中触发crash的代码快照

在某种程度上,这个回答是肯定的

为了演示如何完全触发UAF,我使用了basic string/binary string(BSTR)作为数据结构。SafeArray是一个多维数组,但由于VBsJoin只能处理一位数组,因此我更改了回调中的SafeArray的维度。

不幸的是,它仍然没有用,它会抛出一个运行时错误,指出数组类型在Join中不匹配。不过没有关系,我使用On Error Resume Next来绕过这个运行时错误,下图为修改过后的PoC:

在获得了0x20字节的已释放内存后,我使用大小为0x20字节的BSTR来伪造一个较大size的SafeArray。

通过使用堆风水,这个BSTR可以稳定地重用0x20字节的已释放内存,如下图所示:

我终于得到了一个伪造的一维数组SafeArray,一共有0x7fffffff个元素,每个元素大小为1字节,如下图:

伪造的SafeArray(顶部)和读/写的固定地址(底部)

到目前为止,我已经可以伪造一个SafeArray,可用于读/写0x00000000到0x7fffffff的内存

为了泄露一些读/写地址以便利用,我参考了Simon Zuckerbraun之前的研究并使用堆喷射来获得一些固定的读/写地址(0x28281000)

如Simon Zuckerbraun的博客中所述,我使用Scripting.Dictionary对象来完成远程代码执行,但使用另一种方法来伪造一个假的Dictionary。这一次,我使用了BSTR并将它们带出来

Faked Dictionary内存布局如下:

  1. 使用内存读/写函数来读取原始的Dictionary内存,将其数据保存到一个BSTR,并将VBADictionary::Exists替换为kernel32!Winexec
  2. 将之后用到的Winexec参数\..\clac.exe写入此BSTR
  3. 将此BSTR保存到util_memory+0x1000,并修改util_memory + 0x1000 – 8 = 9以使fake_array(util_memory + 0x1000)成为对象
  4. 使用fake_array(util_memory + &h1000),利用dummy来触发Winexec函数

最终利用结果,成功弹出计算器:

在2019年8月13日,已在Windows 10中禁用的VBScript 又同时在Windows 7,8中禁止IE使用。因此,上文详述的PoC是在本地模式下开发的。但正如微软所说,仍然可以通过注册表或组策略启用此设置。同样,用户和组织应始终采用最佳实践:保证系统打上补丁和保持更新,禁用不需要(或限制使用)的组件,并派样网络安全意识,如垃圾邮件和其它社会工程学威胁

研究的完整细节在本技术简报


文章来源: http://xz.aliyun.com/t/6350
如有侵权请联系:admin#unsafe.sh