使用Refresh Rect PDU和RDPDR客户端名称请求PDU获取具有系统特权的RCE - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

使用Refresh Rect PDU和RDPDR客户端名称请求PDU获取具有系统特权的RCE

xiaohui 技术 2021-01-22 10:10:00
182218
收藏

导语:2019年5月,Microsoft发布了针对远程代码执行(RCE)漏洞CVE-2019-0708的带外修复程序更新,该漏洞也称为“BlueKeep”,位于远程桌面服务(RDS)的代码中。

0.png

2019年5月,Microsoft发布了针对远程代码执行(RCE)漏洞CVE-2019-0708的带外修复程序更新,该漏洞也称为“BlueKeep”,位于远程桌面服务(RDS)的代码中。在过去的一年中,研究人员证明了BlueKeep的可利用性,并提出了检测和预防它的对策。但是,RDP仍然是当今攻击者使用的最受欢迎的攻击媒介之一。为了使RDP攻击更难成功并更好地保护Windows用户,研究人员将在此文中公开有关攻击者如何在Windows RDP终端上利用BlueKeep的详细信息。

在2019年8月,Unit 42的研究人员就对CVE-2019-0708做了详细研究,内容涉及如何使用位图缓存协议数据单元(PDU),Refresh Rect PDU和RDPDR客户端名称请求PDU将数据写入Windows内核内存。此外,2019年10月,Unit 42的研究人员在Microsoft的BlueHat Seattle 2019安全会议上介绍了三种带有RDP PDU新的Windows内核池风水技术和BlueKeep的两种不同利用技术。本文讨论了如何结合使用Refresh Rect PDU和RDPDR客户端名称请求PDU来获得具有系统特权的远程代码执行RCE。

快速查看Refresh Rect PDU和RDPDR客户端名称请求PDU

关于Windows RDP协议中的Refresh Rect PDU和RDPDR客户端名称请求PDU,请点此链接

通过多次发送PDU,Refresh Rect PDU可用于喷洒许多0x828大小的内核池。那些0x828大小的内核池将按0x1000偏移量对齐,在每个0x828大小的内核池中,RDP客户端在偏移0x2c处控制8个字节的数据。八个字节控制数据的起始地址看起来像0x8xxxx02c,在测试过程中,将0x828大小的内核池从地址0x86000000连续整理到0x8a000000,并将0x1000大小的内核池在研究人员的VMware虚拟机上对齐。在概念开发证明(PoC)中,研究人员使用0x86c1002c作为固定地址来存储函数指针,并且在多次重复使用和重新启动系统时获得了很高的成功率。地址0x88xxx02c和0x89xxx02c也是很好的候选对象,它们在高内存消耗目标中表现出色,例如同时运行许多应用程序的RDP服务器。

RDPDR客户端名称请求PDU可通过多次发送PDU来回收具有受控数据的释放通道对象。 RDP服务器解析客户端名称请求PDU时分配的内核池的大小和数据都是可控的。研究人员可以使RDP服务器分配大小为0xd0的内核池,以声明释放的MS_T120通道对象。通过向内核池中注入特制的数据,研究人员可以控制重用路由以使用可控函数指针执行函数调用,从而控制扩展指令指针(EIP)。研究人员也可以使用客户端名称请求PDU将Shellcode写入内核池,因为客户端名称请求PDU的大小和数据都可以由RDP客户端控制。在以下各节中我们将讨论有关在攻击中如何使用这两个PDU的所有详细信息。

漏洞概述

为了明确说明漏洞利用,研究人员将简要介绍CVE-2019-0708发生的根本原因。 CVE-2019-0708是与悬空对象MS_T120虚拟通道相关的Use After Free(UAF)漏洞。 MS_T120虚拟通道是RDP服务器内部使用的两个默认通道(MS_T120和CTXTW)之一,该默认通道在建立RDP连接时初始化。但是,RDP客户端也可以通过将“MS_T120”项添加到客户端MCS Connect初始PDU中的channelDefArray来创建名为“MS_T120”的自定义虚拟通道,如图1所示。

1.png

channelDefArray中的自定义MS_T120通道

RDP服务器接收该请求,并在ChannelPointerTable对象中为MS_T120对象创建引用。图2显示ChannelPointerTable对象中有两个“MS_T120”通道对象引用。第一个为客户端MCS Connect初始PDU请求创建,第二个为RDP服务器内部使用而创建。

2.png

创建自定义的MS_T120通道对象

使用MCS通道加入请求加入自定义的MS_T120通道后,RDP客户端可以成功打开MS_T120通道。如果RDP客户端将制作的数据发送到MS_T120通道(如图3所示),则将调用rdpwx.dll模块中的MCSPortData函数。

3.png

用于释放MS_T120通道对象的PDU

在函数MCSPortData中,从第一个参数lpAddend的0x74偏移开始的数据由RDP客户端控制,并且当变量“v2”等于值“2”时,将调用MCSChannelClose以释放MS_T120通道对象,如图4所示。

4.png

关闭MCSPortData中的通道

在MS_T120通道对象被释放之后,仍然有一个悬空指针在ChannelPointerTable对象的slot 0x1f中指向被释放的MS_T120通道对象,如图5所示。

5.png

释放了自定义的MS_T120通道对象

当RDP客户端断开连接时,将调用函数RDPWD!SignalBrokenConnection,然后将调用函数termdd!IcaChannelInput来访问slot 0x1f中释放的MS_T120对象,如图6所示。

6.png

重用释放的MS_T120对象调用堆栈

释放后重用(Reuse After Free)

如上所述,研究人员已经讨论了如何释放MS_T120通道对象,并在ChannelPointerTable对象中留下了指向MS_T120通道对象的悬空指针。现在,研究人员将介绍如何重用释放的对象。在termdd!IcaChannelInput函数中,将调用函数IcaFindChannel查找通道对象。当RDP客户端终止连接时,第二个参数slot_base将为0x05,第三个参数slot_index将为0x1f,因此函数IcaFindChannel将释放的MS_T120通道对象设置为返回值。如果使用伪造的MS_T120通道对象回收释放的MS_T120通道对象,则可以通过从伪造的MS_T120通道内部获取函数指针(寄存器eax)的函数调用(call [eax])来控制以下函数执行路径对象,如图7所示。

7.png

在IcaChannelInputInternal中重用路由

使用RDPDR客户端名称请求PDU和控制EIP回收释放的MS_T120通道对象

在本节中,我们将讨论如何回收释放的MS_T120通道对象以控制EIP。释放的MS_T120通道的大小为0xc8(包括8个字节的池头的0xd0),如图5所示。termdd!IcaChannelInputInternal函数将分配channel_data_size + 0x20大小的内核池。如果研究人员希望函数termdd!IcaChannelInputInternal函数分配大小为0xc8的内核池,则将客户端名称请求PDU的大小设置为0xa8(0xc8-0x20),并将ComputerNameLen字段相应地设置为0x98。考虑到成功分配池后存在内存复制操作,通过多次发送这些客户端名称请求PDU,研究人员确保释放的MS_T120池slot已被客户端名称请求PDU数据占用。此外,大小为0xc8的内核池的前0x20字节是供termdd模块内部使用的,这意味着前0x20字节是不可控制的,而用于客户端名称请求PDU标头的以下0x10字节也不能控制可控制的,因此可控制的数据大小总计为0x98(0xc8-0x20-0x10)。图8显示了RDP客户端如何构造RDPDR客户端名称请求PDU。

8.png

 RDPDR客户端名称请求回收释放的MS_T120通道对象

图9显示了通过发送RDPDR客户端名称请求PDU创建的虚假MS_T120通道对象的内存转储。伪造的MS_T120通道对象中的几个重要字段以不同的颜色标记。设置为绿色的4字节(DWORD)值0x00000000可以防止服务在hal!KeAcquireInStackQueuedSpinLockRaiseToSynch中崩溃,这由ExEnterCriticalRegionAndAcquireResourceExclusive调用。设置浅蓝色的DWORD值0x00000000以确保条件检查,并使函数路由通过受控的函数指针eax到达函数调用(call [eax])),如图7所示。

9.png

伪造的MS_T120通道对象

紫色的DWORD值0x86c10030设置在伪造的MS_T120通道对象的偏移量0x8c处,如图9所示。图10中的调试日志显示了如何在偏移量0x8c处获取伪造的对象地址并进行函数调用(call [eax])来控制EIP。

10.png

在IcaChannelInputInternal中具有受控函数指针的函数调用

现在,如何控制EIP已经解释清楚了,接下来就要讨论为什么将eax设置为地址0x86c10030,而将EIP设置为地址0x86c1002c。使用上一部分中介绍的技术,可以获得从地址0x86xxxxxx到0x8axxxxxx稳定的喷洒。在每个对齐的0x1000地址中,在偏移0x002c处有8个字节的数据是可以控制的,如图11所示。

11.png

带有Refresh Rect PDU的稳定喷洒

图12中的代码片段显示了RDP客户端如何构造Refresh Rect PDU以及将其发送到RDP服务器需要的次数。

12.png

如何构造Refresh Rect PDU以在RDP客户端中进行喷洒

在每个对齐的0x1000大小的内核池中的8个字节的可控数据中,将偏移量0x0030(0x86c10030)的4个字节设置为0x86c1002c,这是阶段0 shellcode的硬编码地址。偏移量为0x002c(0x86c1002c)的其他4个字节用于存储阶段0的shellcode。下一节将介绍有关Shellcode几个阶段的更多详细信息。

Shellcode

由于只有4个字节可用于阶段0 shellcode,因此研究人员使用了一个4字节shellcode的技巧“add bl,al; jmp ebx”,而不是“call/jmp ebx+30h” 跳转到shellcode中的一个阶段。当termdd!IcaChannelInputInternal执行 “call dword ptr [eax]” 汇编指令时,al为0x30,ebx指向伪造的MS_T120通道对象,RDP客户端可以在其中填充受控数据。第一阶段的shellcode从地址faked_MS_T120_channel_object + 0x30(0x867b3590)进入内核池,整个过程如图13所示。

13.png

阶段 0 Shellcode

值得一提的是,使用2字节的汇编代码 “add bl, al”,因为只能使用4字节的shellcode来实现“jmp ebx+0x30”。 这并不完美,因为当“bl”大于0xd0时,“add bl, al”中会出现溢出,使“jmp ebx”能够跳转到错误的地址,从而导致利用失败。但是,这已经足够好了,因为理论上成功率为81.25% (0xd/0x10)。

在讨论阶段一shellcode之前,研究人员将讨论阶段二或最终的shellcode。研究人员注意到,RDPDR客户端名称请求PDU也可以用于将任意大小的最终内核shellcode发送到RDP服务器中的内核池。例如,研究人员构造了一个RDPDR客户端名称请求PDU,其数据长度为0x5c8,并且嵌入了有效载荷,如图14所示。

14.png

RDPDR客户端名称请求PDU发送的最终shellcode

当将带有Shellcode嵌入的RDPDR客户端名称请求PDU发送到RDP服务器时,PDMCS – Hydra MCS协议驱动程序会将数据存储在内核池中。有趣的是,该内核池在堆栈上维护了一个引用,阶段一shellcode可以使用该引用来定位最终的shellcode。具体来说,此处的ECX寄存器指向堆栈,地址ECX+0x28存储内核池地址。最终的shellcode位于内核池的0x434偏移处,如图15所示。

15.png

阶段一shellcode

偏移量0x434在不同的Windows版本中可能会有所不同,但是,通过在内核池中搜索最终的shellcode,很容易将阶段一shellcode编写为egg hunter ,使其具有通用性。

修复内核以避免崩溃

下面的工作是内核开发的一个例程,最终的shellcode首先修复返回值并修复内核,以免在shellcode完成后崩溃。然后,它执行内核shellcode,以将APC插入lsass.exe或spoolsv.exe并执行用户模式shellcode。图16显示了最终的shellcode如何修复ChannelPointerTable对象,修改返回地址并模拟ExReleaseResourceAndLeaveCriticalRegion函数的执行,以在KTHREAD中包含WORD值。

16.png

最终的shellcode修复内核

修复内核后,将执行内核shellcode的函数部分。为了说明此漏洞利用,研究人员使用了Sleepya发布的内核shellcode模板进行eternalblue漏洞利用。用于演示的WinExec(' calc ')用户shellcode如图17所示。

17.png

最终的shellcode usermode  shellcode

总结

整个攻击链可以描述如下:

1.与受害者建立联系;

2.用Refresh Rect PDU喷洒;

3.发送精心设计的PDU,强制释放MS_T120通道对象;

4.使用多个RDPDR客户端名称请求PDU占用释放的MS_T120通道对象;

5.发送带有RDPDR客户端名称请求PDU的最终shellcode;

6.终止连接以重新使用释放的MS_T120通道对象、控制EIP并执行各个阶段的Shellcode。

本文翻译自:https://unit42.paloaltonetworks.com/cve-2019-0708-bluekeep/如若转载,请注明原文地址:
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务