在2019年8月的例行更新中,微软修复了DejaBlue(CVE-2019-1181/1182)漏洞,称其和BlueKeep(CVE-2019-0708)一样也是wormable的,并且影响win7-win10的操作系统。下面我们就来探究一下这两个漏洞(环境win10 64bit)。
因为DejaBlue是在每月例行更新中修复的,并不像BlueKeep一样有单独的补丁包,所以首先需要确定存在漏洞的组件。在checkpoint的一篇文章中提到了windows系统中与RDP有关的组件。
经过分析,最终确定存在漏洞的组件为rdpbase.dll,通过补丁对比确定了存在漏洞的函数为DecompressUnchopper::Decompress。
有两处不同,看上去都像是增加了对整数溢出的判断。
第一处:
After
Before
第二处:
After
Before
在这个函数下断点试试。这里调试方法和BlueKeep有所不同,BlueKeep中存在漏洞的组件是一个内核态组件,需要使用内核调试的方法进行调试;DejaBlue中存在漏洞的组件是一个用户态组件,对windows系统有所了解的话应该知道这种服务的组件是通过svchost加载的,以管理员权限启动Process Explorer搜索rdpbase.dll就可以找到相应的svchost进程,再用管理员权限启动windbg即可附加进程调试。然而下断点建立RDP连接之后并没有断下来,只好尝试静态分析找一找调用该函数的方法。
DecompressUnchopper::DecompressUnchopper应该是DecompressUnchopper类的构造函数,DecompressRdp8__CreateInstance调用了DecompressUnchopper::DecompressUnchopper。rdpbase.dll中导出了该函数,rdpserverbase.dll中导入了该函数,调用链依次是CRdpDynVCMgr::HandleIncomingDvcData->CRdpDynVC::GetDecompressor-> DecompressRdp8__CreateInstance。DynVC指的是Dynamic Virtual Channel,rdesktop中的dvc.c就有相应的实现。能够在dvc.c中看到dvc_channel的回调函数是dvc_process_pdu,dvc_process_pdu中有DYNVC_DATA_COMPRESSED这样的case,能够和在IDA中看到的函数名对应上。
找到微软关于RDP的文档中与Dynamic Virtual Channel有关的文档([MS-RDPEDYC].pdf),猜测我们可能需要发送DVC Data First Compressed PDU或者DVC Data Compressed PDU。
我们用rdesktop建立连接看看:RDESKTOP_DEBUG=Protocol ./rdesktop 192.168.112.132
在Opening a DVC这一步当收到DVC Create Request PDU之后因为没有找到对应的channel所以不能进行到Sending and Receiving Data这一步。
阅读文档我们可以知道必须先发送DVC Data First Compressed PDU才能发送DVC Data Compressed PDU,DVC Data First Compressed PDU的格式如下所示。
Data的格式为RDP_SEGMENTED_DATA,在另一个文档里面([MS-RDPEGFX].pdf)。
阅读文档之后我们对rdesktop的代码进行一些修改。从前面图片中的dvc_process_pdu函数中可以看到rdesktop是并没有实现Sending and Receiving Data这部分逻辑的,需要自己构造。首先在dvc_init函数中注册一个收到的DVC Create Request PDU中request的channel。
在收到DVC Create Request PDU之后进行处理的dvc_process_create_pdu函数中发送DVC Create Response PDU的dvc_send_create_response函数之后增加发送DVC Data First Compressed PDU的dvc_send_first_compressed函数。
dvc_send_first_compressed函数按照文档构造即可。注意到文档中RDP_SEGMENTED_DATA结构的descriptor可为0xE0或0xE1,从前面图片中的DecompressUnchopper::Decompress函数中可以看到a2=255(0xE1)才会进入存在漏洞的路径,因此descriptor要按照0xE1构造。RDP8_BULK_ENCODED_DATA结构中的数据来自文档中的示例。
这一次成功断下,对照dvc_send_first_compressed函数可以知道是uncompressedSize字段发生了整数溢出。
将dvc_send_first_compressed函数中的uncompressedSize字段改成0xffffe001,溢出之后即为0x1,而根据文档中的示例发送的数据解压之后是1595个字节的q(0x71),这样肯定会造成堆溢出。果然这里发送的数据导致了crash。
以我有限的知识水平来看,利用起来应该比较困难或者可能还需要其它漏洞配合。
参考资料:
1.DejaBlue: Analyzing a RDP Heap Overflow
2.Reverse RDP Attack: Code Execution on RDP Clients
3.Patch new wormable vulnerabilities in Remote Desktop Services (CVE-2019-1181/1182)