一、概述
远程桌面协议(RDP)被全球数以千计的IT专业人员和安全研究人员使用,它通常被认为是连接到远程计算机的安全可靠的应用程序。无论是用于帮助远程工作人员还是在安全的VM环境中工作,RDP客户端都是非常宝贵的工具。
但是,Check Point Research最近在常用的远程桌面协议(RDP)中发现了多个严重漏洞,这些漏洞允许恶意行为者反向通常的通信方向并感染IT专业人员或安全研究的计算机。 这种感染可能会导致整个IT网络的入侵。
我们总共发现了16个严重漏洞和25个安全漏洞。 完整列表可在附录A和B中找到。
二、介绍
远程桌面协议(RDP),在Microsoft内置RDP客户端之后也称为“mstsc”,技术用户和IT人员通常使用它来连接远程计算机上。 RDP是Microsoft开发的专有协议,通常在用户想要连接到远程Windows机器时使用。还有一些流行的RDP协议开源客户端主要由Linux和Mac用户使用。
RDP提供许多复杂功能,例如:压缩视频流,剪贴板共享和多个加密层。因此,我们决定寻找协议及其流行实现中的漏洞。
在正常情况下,使用RDP客户端,并连接到远程计算机上安装的远程RDP服务器。成功连接后,可以根据用户的权限访问和控制远程计算机。但如果情景可以反过来?我们想调查RDP服务器是否可以攻击并控制连接的RDP客户端。
图1:RDP协议的攻击场景
有几种常见的情形,攻击者可以通过部署此类攻击获得提升的网络权限,从而推进他在企业内部的横向移动:
1. 攻击连接到企业网络内受感染工作站的IT成员,从而获得更高的权限级别和更大的网络系统访问权限。
2. 攻击连接到包含经过测试的恶意软件的远程沙盒虚拟机的恶意软件研究人员。这允许恶意软件逃离沙箱并渗透到企业网络中。
确定了攻击向量之后,来介绍一下我们的目标,最常用的RDP客户端:
· mstc.exe – 微软内置的RDP客户端。
· FreeRDP – Github上最流行,最成熟的开源RDP客户端。
· rdesktop – Older开源RDP客户端,默认出现在Kali-linux发行版中。
有趣的事实:由于“rdesktop”是Kali-linux(红队用于渗透测试的Linux发行版)中的内置客户端,我们想到了第三种(尽管可能不实用)的攻击场景:蓝队可以安装组织蜜罐和攻击试图通过RDP协议连接到它们的红队。
三、开源RDP客户端
正常情况下,我们决定开始寻找开源客户端中的漏洞。在我们对协议有了一个充分的了解之后,只有开始对微软的客户进行逆向才有意义。此外,如果在两个开源客户端中发现常见漏洞,我们可以检查它们是否也适用于Microsoft的客户端。“rdesktop”小于“FreeRDP”(代码行数较少),因此在重新检查中我们选择它作为第一个目标。
注意:我们决定执行老式的手动代码审核,而不是使用任何模糊测试技术。 这个决定的主要原因是为复杂的RDP协议编写专用模糊器的开销太大,以及将AFL用于具有多个压缩和加密层的协议看起来也不是一个好主意。
(一)rdesktop (测试版本 v1.8.3)
在短暂的一段时间后,我们决定手动搜索漏掉的漏洞。我们很快就发现了代码中几个易受攻击的模式,使得“感觉”代码更容易,并查明可能的漏洞的位置。
我们发现11个漏洞具有重大安全隐患,并且库中总共有19个漏洞。 有关“rdesktop”的完整CVE列表,请参阅附录A.
注意:另一个调查显示xrdp开源RDP服务器基于“rdesktop”代码。根据我们的调查结果,在“xrdp”中也可以找到类似的漏洞。
我们将重点关注自身发现的两种常见的存在漏洞的代码模式,而不是对所有CVE进行技术分析。
1、远程代码执行 – CVEs 2018-20179 – 2018-20181
在整个客户端代码中,假设服务器向客户端发送了足够的字节来进行处理。可以在图2中的以下代码片段中找到此假设的一个示例:
图2:在没有首先检查其大小的情况下从stream “s”解析2个字段
正如我们所看到的,字段“length”和“flags”是从流“s”中解析出来的,而不检查“s”确实包含了这个解析操作所需的8个字节。虽然这通常只会导致越界读取,但我们可以将此漏洞与多个内部通道中的其他漏洞相结合,从而实现更严重的影响。
有三个逻辑通道共享一个共同的漏洞:
· lspci
· rdpsnddbg – 是的,此调试通道始终处于活动状态
· seamless
漏洞本身可以在图3中看到:
图3:计算剩余“pkglen”时的整数向下溢出
通过从流中读取太多数据,即将数据包发送到客户端,“s-> p <= s-> end”的不变量中断。这会在计算“pkglen”时导致整数向下溢出,并在为缓冲区分配“xmalloc(pkglen + 1)”字节时导致额外的整数溢出,正如上面对“xmalloc”调用的注释中所示。
与图4中所示的“STRNCPY”的专有实现一起,当将数据复制到微小的分配堆缓冲区时,我们可以触发大量的基于堆的缓冲区溢出。
图4:“strncpy”函数的专有实现
将在三个不同的逻辑通道中发现的这两个漏洞链接起来,我们现在有了三个远程代码执行漏洞。
2、CVE 2018-8795 –远程代码执行
另一个经典漏洞是处理收到的位图(屏幕内容)更新时的整数溢出,如图5所示:
图5:处理位图更新时的整数溢出
虽然“宽度”和“高度”都只有16比特,但通过将它们与“Bpp”(每像素位数)相乘,我们可以触发整数溢出。稍后,位图解压缩将处理我们的输入并中断任何解压缩错误,从而为我们提供可控制的基于堆的缓冲区溢出。
注意:这个棘手的计算可以在“rdesktop”代码的几个地方找到,因此我们将其标记为在“FreeRDP”中检查的潜在漏洞。
(二)FreeRDP (测试版本 2.0.0-rc3)
在“rdesktop”中发现多个漏洞之后,我们对“FreeRDP”也感到有些不安;或许只有“rdesktop”在实施RDP时存在漏洞?我们无法确定协议的每个实施都会容易受到攻击。
事实上,乍一看,代码要好得多:在从接收到的数据包中解析数据之前进行了最小size的检查,并且代码“感觉”更加成熟。这将是一个挑战。然而,经过深入研究后,我们开始发现代码中存在问题,最终发现了该客户端的关键漏洞。
我们发现5个漏洞具有重大安全隐患,并且库中总共有6个漏洞。有关“FreeRDP”的完整CVE列表,请参阅附录B.
注意:另一个侦察显示NeutrinoRDP是旧版本(1.0.1)的“FreeRDP”的分支,因此可能存在相同的漏洞。
在研究结束时,我们为CVE 2018-8786开发了一个PoC漏洞,如本视频所示:https://www.youtube.com/embed/eogkRQtcm6U?feature=oembed
1、CVE 2018-8787 – 同样的整型溢出
正如我们之前在“rdesktop”中看到的那样,计算接收到的位图更新的size容易受到整数溢出的影响。事实上,“FreeRDP”也有同样的漏洞:
图6:处理位图更新时的相同整数溢出
2、远程代码执行 – CVE 2018-8786
图7:处理位图更新时的Integer-Truncation
从图7中可以看出,在尝试计算位图更新数组所需的大小时会出现Integer-Truncation。稍后,从数据包中解析出的矩形结构将分配到一个小的内存缓冲区中。
当解析矩形并将其存储到数组时,此特定漏洞后面是堆分配的受控量(“bitmapUpdate-> number”),从而为攻击者提供了一个很好的堆溢出。这个漏洞的缺点是大多数矩形字段只有16位宽,并被扩展成32位以存储在数组中。尽管如此,我们还是设法在PoC中利用了这个CVE。这种部分受控的基于堆的缓冲区溢出也足以进行远程代码执行。
四、Mstsc.exe –微软RDP客户端(Build 18252.rs_prerelease.180928-1410)
在完成对开源代码的检查之后,我们觉得自己对协议有了很好的理解,现在可以开始对Microsoft的RDP客户端进行逆向。但首先,我们需要找到哪些二进制文件包含我们想要检查的逻辑。我们选择关注的* .dll文件和* .exe文件:
· dll – RDP客户端的协议层.
· dll –RDP服务器的协议层.
· dll / rdpcorets.dll – RDP引擎的核心逻辑.
· exe – 我们发现的.exe,稍后会介绍。
· dll – Mstsc.exe使用的RDP逻辑大致相同。
(一)测试之前的漏洞
我们首先测试开源客户端中的漏洞PoC。不幸的是,所有这些都导致客户端干净利落地关闭,没有任何崩溃。我们开了IDA并开始跟踪消息流。很快,我们意识到微软的实现比我们之前测试的实现要好得多。实际上,微软的代码要好几个数量级,因为它包含:
· 几个优化层,用于接收视频的高效网络流。
· Robust输入检查。
· Robust解压缩检查,以确保不会通过目标缓冲区写入任何字节。
· 附加支持的剪贴板功能。
· …
不用说,在处理位图更新时会检查整型溢出。
(二)共享剪贴板
当我们检查“rdesktop”和“FreeRDP”时,我们发现剪贴板共享通道中存在多个漏洞(每个逻辑数据层称为一个通道)。但是,当时我们并不太关注它,因为它们只共享两种格式:原始文本和Unicode文本。但微软支持多种共享数据格式,因为我们看到的交换表比之前大得多。
在阅读了MSDN中有关不同格式的更多信息后,一种格式立即引起了我们的注意:“CF_HDROP”。这种格式负责“拖放”(因此名称为HDROP),在我们的例子中就是“复制和粘贴”功能。可以简单地从第一台计算机复制一组文件,然后将它们粘贴到第二台计算机中。例如,恶意软件研究人员希望将其脚本的输出日志从远程VM复制到其桌面。
大致是在这一点上,当我试图弄清楚数据流时,Omer(@GullOmer)问我是否以及在哪里调用PathCanonicalizeA。如果客户端无法正确规范化并清理它接收的文件路径,则容易受到路径遍历攻击,允许服务器在客户端计算机上的任意路径释放任意文件,这是一种非常强大的攻击。在未能找到规范化函数的导入之后,我们深入挖掘,试图找出该数据流的整体架构。
图8总结了我们的发现:
图8:Microsoft RDP中共享剪贴板的体系结构
这是rdpclip.exe发挥作用的地方。事实证明,服务器通过broker访问剪贴板,即rdpclip.exe。实际上,rdpclip.exe只是一个正常的进程(我们可以自己终止/生成),它使用专用的虚拟通道API与RDP服务对话。
在这个阶段,我们安装了ClipSpy,并开始动态调试rdpclip.exe中完成的剪贴板数据处理。
这些是关于普通“复制和粘贴”操作中数据流的结论,其中文件从服务器复制到客户端:
1. 在服务器上,“复制”操作创建格式为“CF_HDROP”的剪贴板数据。
2. 当在客户端的计算机中执行“粘贴”时,会触发一系列事件。
3. 要求服务器上的rdpclip.exe进程提供剪贴板的内容,并将其转换为FileGroupDescriptor(Fgd)剪贴板格式。
4. 使用HdropToFgdConverter :: AddItemToFgd函数,将文件的元数据一次添加到描述符中。
5. 完成后,将Fgd blob发送到服务器上的RDP服务。
6. 服务器只需将其打包并发送给客户端。
7. 客户端解包并将其存储在自己的剪贴板中。
8. “粘贴”事件被发送到当前窗口的进程(例如,explorer.exe)。
9. 此进程程处理事件并从剪贴板读取数据。
10. 文件的内容是通过RDP连接本身接收的。
(三)路径遍历——共享RDP剪贴板
回顾对收到的剪贴板数据执行的步骤,我们会注意到客户端没有验证从RDP服务器收到的收到的Fgd blob。事实上,如果我们修改服务器以包含以下形式的路径遍历路径:..\canary1.txt,ClipSpy展示(参见图9)它在客户端的剪贴板上“按原样”存储:
图9:带有路径遍历的Fgd存储在客户端的剪贴板上
在图10中,我们可以看到explorer.exe如何处理..\filename.txt的路径遍历:
图10:explorer.exe处理带有路径遍历的Fgd
取而代之,文件存储到“Base”中,而不是其“Inner”子文件夹:
图11:路径遍历攻击成功之后的文件夹
事实就是这样。
如果客户端通过RDP连接使用“复制和粘贴”功能,则恶意RDP服务器可以透明地将任意文件释放到客户端计算机上的任意位置,仅受客户端权限的限制。 例如,我们可以将恶意脚本释放到客户端的“Startup”文件夹中,重启后,它将在客户端计算机上执行,从而完全受控。
注意:在漏洞利用中,我们简单地杀死了rdpclip.exe,并通过向每个“复制和粘贴”操作添加额外的恶意文件来生成自己的进程以执行路径遍历攻击。攻击是使用“用户”权限执行的,并未要求攻击者拥有“系统”或任何其他高权限。
PoC漏洞视频:https://www.youtube.com/embed/F70FGv_QxDY?feature=oembed
(四)更进一步
每次在RDP连接的任一端更新剪贴板时,都会向另一端发送CLIPRDR_FORMAT_LIST消息,以通知它现在可用的新剪贴板格式。 我们可以将其视为双方剪贴板之间的完全同步(除了RDP连接本身区别对待的一小部分格式之外)。 这意味着只要客户端将某些内容复制到他的“本地”剪贴板,就会通知恶意服务器,现在它可以查询这些值并读取它们。此外,服务器可以向客户端通知剪贴板“更新”,而无需在RDP窗口内进行“复制”操作,从而完全控制客户端的剪贴板而不会被注意到。
场景 #1:
恶意RDP服务器可以窃听客户端的剪贴板 – 这是一个功能,而不是bug。 例如,客户端本地复制管理员密码,服务器上也会有。
场景 #2:
恶意RDP服务器可以修改客户端使用的任何剪贴板内容,即使客户端未在RDP窗口内发出“复制”操作。 如果在打开RDP连接时单击“粘贴”,则很容易受到此类攻击。 例如,如果在计算机上复制文件,服务器可以修改(可执行文件?)文件/保留副本,以使用之前显示的PoC添加其他文件/路径遍历文件。
我们能够使用NCC’s .NET deserialization PoC成功测试此攻击情形:
1. 服务器执行其PoC,并在剪贴板中放置弹出计算器的.NET(使用“System.String”格式)。
2. 当客户端在PowerShell程序中单击“粘贴”时,将发生反序列化并弹出计算结果。
注意:同步剪贴板的内容受延迟渲染的影响。这意味着只有在程序主动询问(通常是单击“粘贴”)后才能通过RDP连接发送剪贴板的内容。在此之前,剪贴板仅保留可用格式列表,而不保留内容本身。
五、时间表
· 2018年10月16日 – 向Microsoft披露了漏洞。
· 2018年10月22日 – 向FreeRDP披露了漏洞。
· 2018年10月22日 – FreeRDP回复并开始研究补丁。
· 2018年10月28日 – 向rdesktop披露了漏洞。
· 2018年11月5日 – FreeRDP向我们发送补丁并要求我们验证。
· 2018年11月18日 – 我们验证了FreeRDP的补丁,并给他们一个“绿灯”。
· 2018年11月20日 – FreeRDP将补丁作为2.0.0-rc4的一部分提交给他们的Github。
· 2018年12月17日 – 微软承认我们的调查结果。 有关更多信息,请参阅Microsoft的响应。
· 2018年12月19日 – rdesktop向我们发送补丁并要求我们验证。
· 2018年12月19日 – 我们验证了rdesktop的补丁,并给了他们一个“绿灯”。
· 2019年1月16日 – 作为v1.8.4的一部分,rdesktop将补丁提交到了他们的Github。
六、Microsoft响应
在负责任的披露过程中,我们将mstsc.exe中的路径遍历的详细信息发送给了Microsoft。
这是微软的官方回应:
感谢提交。我们确定您的发现是有效的,但不符合我们的服务标准。有关详细信息,请参阅Windows的Microsoft安全服务标准(https://aka.ms/windowscriteria)。
因此,此路径遍历没有CVE-ID,也没有补丁来解决。
七、总结
在研究中,我们在测试的RDP客户端中发现了许多严重漏洞。虽然不同客户端的代码质量各不相同,但从发现的漏洞分布可以看出,我们认为远程桌面协议很复杂,容易出现漏洞。正如我们在Microsoft客户端和一个开源客户端演示的PoC那样,恶意RDP服务器可以利用RDP客户端中的漏洞来实现客户端计算机上的远程代码执行。
由于IT人员和技术人员经常使用RDP连接到远程计算机,我们强烈建议每个人都修补他们的RDP客户端。此外,由于我们在Microsoft的RDP客户端中显示的剪贴板问题,我们建议用户在连接到远程计算机时禁用剪贴板共享通道(默认情况下已启用)。
八、推荐保护措施
Check Point建议采取以下步骤以防止此类攻击:
1. Check Point Research与FreeRDP,rdesktop和Microsoft紧密合作,以缓解这些漏洞。如果使用的是rdesktop或FreeRDP,请更新到包含相关䃼丁程序的最新版本。
2. 当使用Microsoft RDP客户端(MSTSC)时,我们强烈建议禁用RDP上的双向剪贴板共享。
3. 对RDP通信中涉及的客户端和服务器应用安全措施。
4. Check Point提供可用于保护的各种安全层,例如IPS,SandBlast Agent,威胁仿真和ANTEX。
5. 用户应避免使用RDP连接到未实施足够安全措施的远程服务器。
Check Point的IPS blade提供针对这些威胁的保护:
1. “FreeRDP远程执行代码(CVE-2018-8786)”
附录 A – rdesktop中的CVEs :
· CVE 2018-8791: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function rdpdr_process() that results in an information leak.
· CVE 2018-8792: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function cssp_read_tsrequest() that results in a Denial of Service (segfault).
· CVE 2018-8793: rdesktop versions up to and including v1.8.3 contain a Heap-Based Buffer Overflow in function cssp_read_tsrequest() that results in a memory corruption and probably even a remote code execution.
· CVE 2018-8794: rdesktop versions up to and including v1.8.3 contain an Integer Overflow that leads to an Out-Of-Bounds Write in function process_bitmap_updates() and results in a memory corruption and possibly even a remote code execution.
· CVE 2018-8795: rdesktop versions up to and including v1.8.3 contain an Integer Overflow that leads to a Heap-Based Buffer Overflow in function process_bitmap_updates() and results in a memory corruption and probably even a remote code execution.
· CVE 2018-8796: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function process_bitmap_updates() that results in a Denial of Service (segfault).
· CVE 2018-8797: rdesktop versions up to and including v1.8.3 contain a Heap-Based Buffer Overflow in function process_plane() that results in a memory corruption and probably even a remote code execution.
· CVE 2018-8798: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function rdpsnd_process_ping() that results in an information leak.
· CVE 2018-8799: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function process_secondary_order() that results in a Denial of Service (segfault).
· CVE 2018-8800: rdesktop versions up to and including v1.8.3 contain a Heap-Based Buffer Overflow in function ui_clip_handle_data() that results in a memory corruption and probably even a remote code execution.
· CVE 2018-20174: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function ui_clip_handle_data() that results in an information leak.
· CVE 2018-20175: rdesktop versions up to and including v1.8.3 contains several Integer Signedness errors that leads to Out-Of-Bounds Reads in file mcs.c and result in a Denial of Service (segfault).
· CVE 2018-20176: rdesktop versions up to and including v1.8.3 contains several Out-Of-Bounds Reads in file secure.c that result in a Denial of Service (segfault).
· CVE 2018-20177: rdesktop versions up to and including v1.8.3 contain an Integer Overflow that leads to a Heap-Based Buffer Overflow in function rdp_in_unistr() and results in a memory corruption and possibly even a remote code execution.
· CVE 2018-20178: rdesktop versions up to and including v1.8.3 contain an Out-Of-Bounds Read in function process_demand_active() that results in a Denial of Service (segfault).
· CVE 2018-20179: rdesktop versions up to and including v1.8.3 contain an Integer Underflow that leads to a Heap-Based Buffer Overflow in function lspci_process() and results in a memory corruption and probably even a remote code execution.
· CVE 2018-20180: rdesktop versions up to and including v1.8.3 contain an Integer Underflow that leads to a Heap-Based Buffer Overflow in function rdpsnddbg_process() and results in a memory corruption and probably even a remote code execution.
· CVE 2018-20181: rdesktop versions up to and including v1.8.3 contain an Integer Underflow that leads to a Heap-Based Buffer Overflow in function seamless_process() and results in a memory corruption and probably even a remote code execution.
· CVE 2018-20182: rdesktop versions up to and including v1.8.3 contain a Buffer Overflow over the global variables in function seamless_process_line() that results in a memory corruption and probably even a remote code execution.
附录 B – FreeRDP中的CVEs :
· CVE 2018-8784: FreeRDP prior to version 2.0.0-rc4 contains a Heap-Based Buffer Overflow in function zgfx_decompress_segment() that results in a memory corruption and probably even a remote code execution.
· CVE 2018-8785: FreeRDP prior to version 2.0.0-rc4 contains a Heap-Based Buffer Overflow in function zgfx_decompress() that results in a memory corruption and probably even a remote code execution.
· CVE 2018-8786: FreeRDP prior to version 2.0.0-rc4 contains an Integer Truncation that leads to a Heap-Based Buffer Overflow in function update_read_bitmap_update() and results in a memory corruption and probably even a remote code execution.
· CVE 2018-8787: FreeRDP prior to version 2.0.0-rc4 contains an Integer Overflow that leads to a Heap-Based Buffer Overflow in function gdi_Bitmap_Decompress() and results in a memory corruption and probably even a remote code execution.
· CVE 2018-8788: FreeRDP prior to version 2.0.0-rc4 contains an Out-Of-Bounds Write of up to 4 bytes in function nsc_rle_decode() that results in a memory corruption and possibly even a remote code execution.
· CVE 2018-8789: FreeRDP prior to version 2.0.0-rc4 contains several Out-Of-Bounds Reads in the NTLM Authentication module that results in a Denial of Service (segfault).