五月份的周二补丁日修补了今年最令人担忧的Windows终端服务漏洞(CVE-2019-0708)。 然而还有另一个无法忽略的远程代码执行(RCE)漏洞:CVE-2019-0725
——Windows动态主机配置协议(DHCP)服务器中的RCE漏洞需要引起我们的注意。 与DHCP相关的漏洞在今年的Patch Tuesdays
中引起了越来越多的关注。 一个例子是去年2月在DHCP服务器上修补的另一个RCE漏洞(CVE-2019-0626)。
CVE-2019-0725不需要用户交互,并且会影响所有版本的Windows Server。 CVE-2019-0725究竟有多大的影响和可利用性?
CVE-2019-0725的影响
微软对CVE-2019-0725
的CVSS 3.0评级的基本评分为8.1。 攻击成功后会造成系统级代码执行,如高机密性、完整性和可用性影响。 所有版本的Windows Server中的漏洞严重程度都被评为严重。 此外,成功攻击并不需要特权。
但是,其攻击复杂性评级很高,这意味着该漏洞可能是一个主要利用的诱因,并未完全受到攻击者的控制。 在这种情况下,该评级较低的部分是由于漏洞是由竞争条件引起。
这种竞争条件究竟如何利用? 让我们快速了解一般通过DHCP分配地址的方式。
希望分配IP地址的客户端将首先发送DISCOVER
消息,通常发送到广播地址(FF:FF:FF:FF:FF:FF
硬件层以及IP层的255.255.255.255
)。 如果同一广播域中有DHCP服务器,并且它具有可分配的IP地址,则它将以OFFER消息进行响应。 它包含客户端应使用的IP
地址的详细信息,以及DNS
服务器等其他信息。
然后,DHCP
客户端发送REQUEST
消息,其中包含有关客户端的其他信息,并确认客户端请求的IP地址(通常是服务器在OFFER
消息中发送的地址)。 如果服务器接受来自客户端的REQUEST
消息,它将发送DHCP ACK
以通知客户端它现在可以使用分配的IP地址。 这里我们需要记住这些信息,之后详细了解一下漏洞本身。
触发竞争条件并利用漏洞
DHCP
服务器在dhcpssvc.dll
中实现,并通过svchost.exe
运行。 传入的DHCP
消息由ProcessMessage()
函数处理。 它首先调用一个函数从传入消息中提取DHCP
选项。 这是因为DHCP选项包含诸如请求的IP地址、主机名以及最重要的DHCP消息类型(例如,DISCOVER
或REQUEST
)之类的信息。 ProcessMessage()
将根据DHCP消息类型调用处理函数。 在DISCOVER
消息的情况下,调用的函数是ProcessDhcpDiscover()
,而此函数可以造成后面的漏洞。DHCP
服务器在dhcpssvc.dll
中实现,并通过svchost.exe
运行。
Windows DHCP
服务器将追踪“待处理”的IP地址。这意味着IP地址已在内部分配给客户端,但不一定由客户端提供或接受。为了跟踪这些待处理部分,DHCP服务器使用PendingCtxt
结构的引用列表。这些PendingCtxt
结构包含在堆的缓冲区中,包括客户端硬件地址、租约情况、续订和重新绑定时间、分配给客户端的IP地址以及指定是否已为此特定项发送了OFFER
的标志等信息。首次调用ProcessDhcpDiscover()
时,它会检查它是否具有现有的PendingCtxt
。它通过使用DHCP
头中包含的客户端硬件地址作为函数DhcpFindPendingCtxt()
的参数来实现此目的。
如果没有为特定客户端找到当前的PendingCtxt
,则从可用地址池或先前分配给该客户端的地址分配地址。然后调用函数DhcpProcessDiscoverForValidatedAddress()
以执行构造将响应DISCOVER
发送的OFFER
消息所需的剩余任务。 DhcpProcessDiscoverForValidatedAddress()
检索配置的租约信息,例如服务器上配置的租约、续订和重新绑定时间。然后将该信息以及提供的IP地址和子网掩码传递给函数DhcpAddPendingCtxt()
。该函数为新的PendingCtxt
结构分配一个堆缓冲区,该结构填充了待处理的租约信息,然后添加到所有待处理租约的列表中。
添加PendingCtxt
结构后将在函数DhcpRespondToDiscover()
中构造OFFER
消息并将其发送到客户端。
因为PendingCtxt
结构理论上可以在任何时间点由多个服务器线程访问,所以对结构的访问通常包含在DhcpGlobalInprogressCritSect
关键部分中。 这仅允许一个线程或进程在关键部分内运行限制共享访问相同资源而导致的意外行为。 在ProcessDhcpDiscover()
中,在调用DhcpFindPendingCtxtI()
之前输入DhcpGlobalInprogressCritSect
临界区。 如果没有PendingCtxt
,或者在现有PendingCtxt
结构中的某些信息被验证之后,线程将离开临界区。
但是,在线程离开这个初始临界区之后,还有一个由位于RBX
寄存器中的地址引用的PendingCtxt
结构的直接访问过程。 此访问检查“OFFER
标志”的值以查看是否已将OFFER
发送到此客户端。 虽然这种直接访问受到保护,但是在离开前一个关键部分和进入新的关键部分之间有一个很小的窗口期。
由于线程调度的不可预测性,所以我们不能保证PendingCtxt
结构仍然存在。 删除PendingCtxt
结构的线程可以选择在ProcessDhcpDiscover()
离开第一个临界区之后但在函数进入下一个临界区之前运行。 当再次访问PendingCtxt
结构时,此竞争条件可在空闲后使用。
有几种情况可能导致PendingCtxt
结构被释放,这是由函数DhcpDeletePendingCtxt()
执行的任务。PendingCtxt
可能会过期并被清理,并且攻击者无法控制。 但是,发送带有服务器无法分配的请求IP地址的REQUEST消息或RELEASE消息将导致调用DhcpDeletePendingCtxt()
并释放先前分配的堆缓冲区。
可利用性
攻击者可以通过发送至少两个DISCOVER
消息以便在空闲后触发使用漏洞。可以发送一个用于创建初始PendingCtxt
,另一个用于查找和访问创建的PendingCtxt
。攻击者还必须发送定时的RELEASE
或特殊的REQUEST
消息。
实际上,在第一次尝试时实际上不可能触发这样的竞争条件。攻击者必须同时发送大量DISCOVER
和RELEASE
或REQUEST
消息。我们的测试显示,需要10秒到几分钟才能触发竞争状态。我们的客户端也一直发送这些DHCP消息。
虽然触发漏洞看起来很容易,但实际上获得代码执行是具有挑战性的。攻击者需要在网络上创建大量流量才有机会。但是,由于触发漏洞可能导致DHCP
服务器服务崩溃,攻击者可能会使用此拒绝服务功能来运行可用于执行DNS缓存中毒等攻击的恶意DHCP服务器。
本文为翻译文章,本文来自:[https://blog.trendmicro.com/trendlabs-security-intelligence/cve-2019-0725-an-analysis-of-its-exploitability/](https://blog.trendmicro.com/trendlabs-security-intelligence/cve-2019-0725-an-analysis-of-its-exploitability/)