从BinDiff到0day 在IE中利用CVE-2019-1208

前言

如上所述,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的代码快照

PoC是否成功触发UAF?

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

为了演示如何完全触发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)

从UAF到RCE

如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函数

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

这个漏洞对IE意味着什么?

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

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

猜你喜欢

转载自blog.csdn.net/weixin_55436205/article/details/130659577