一、事件背景
2024年7月9日,微软官方发布了一个针对“windows远程桌面授权服务远程代码执行漏洞”(CVE-2024-38077)的修复补丁包,起初并没有引起大家的警觉。今日在国外某网站上疑似漏洞的作者公开了该漏洞的“POC验证代码”。一时激起千层浪,该漏洞开始疯狂发酵并在安全圈里转发。
该文章的原文链接为:
https://sites.google.com/site/zhiniangpeng/blogs/MadLicense
链接里也附上了漏洞验证视频:
https://www.youtube.com/watch?v=OSYOrRS2k4A&t=8s
有意思的是,截至本文发稿前,这篇文章和文章里提到的漏洞验证视频已均被作者删除。我们就先从作者发的这个链接来看看其中的一些端倪。
二、原文翻译
注:以下内容为原文翻译,我们对其中需重点关注的部分做了标记。
【背景】
今年早些时候,我们对 Windows 远程桌面服务进行了深入分析,发现了多个漏洞,所有相关漏洞(56 例)都已报告给微软。其中包括远程桌面授权服务中的多个 Preauth RCE 漏洞(未经身份验证的非沙盒 0-click RCE)。这些漏洞可用于构建针对 Windows 远程桌面授权服务的多个 Preauth RCE 漏洞。是的,它们是多年来在 Windows 中未见过的 0-click preauth RCE。我们将它们称为Mad、Bad 和 Dead Licenses 漏洞。
本文是关于这些漏洞的系列文章中的第一篇。
在本文中,我们介绍了漏洞 CVE-2024-38077(我们将其命名为 MadLicense【狂躁许可】),并在启用了完整和新缓解措施的 Windows Server 2025 上演示了该漏洞的利用。我们之所以选择 Windows Server 2025,是因为微软声称 Windows Server 2025 提供了下一代安全改进。并且该漏洞适用于 Windows Server 2000到2025(所有 Windows Server )。
我们现在不会给出详细的技术解释,也不会提供完整的POC 。但是这里的伪代码足以了解此漏洞。为了防止滥用,此处的 python 代码实际上是伪代码。你甚至无法使用此伪代码触发漏洞,更不用说利用它了。这足以证明其严重性,并为防御者在真正弄清楚如何利用它之前采取行动提供足够的时间。
我们在一个月前就通知微软这个漏洞可以被利用,但微软仍将其标记为不太可能被利用。因此我们在此进行了负责任的披露。我们的目的是提高人们对该漏洞风险的认识,并鼓励用户及时更新系统以解决这些问题。Defender 还可以使用本博客中的信息来检测和阻止可能的攻击。
【介绍】
2024年7月,我们报告的以下7个与RDP相关的漏洞已被Microsoft修复:
CVE-2024-38077:Windows 远程桌面授权服务远程代码执行漏洞
CVE-2024-38076:Windows 远程桌面授权服务远程代码执行漏洞
CVE-2024-38074:Windows 远程桌面授权服务远程代码执行漏洞
CVE-2024-38073:Windows 远程桌面许可服务拒绝服务漏洞
CVE-2024-38072:Windows 远程桌面授权服务拒绝服务漏洞
CVE-2024-38071:Windows 远程桌面许可服务拒绝服务漏洞
CVE-2024-38015:Windows 远程桌面网关(RD 网关)拒绝服务漏洞
其中,Windows 远程桌面授权服务中的 3 个 CVSS 评分为 9.8 的 RCE 漏洞值得关注。在微软的公告中,他们认为这些漏洞不太可能被利用。但事实并非如此。事实上,我们在补丁发布之前就告知了微软这些漏洞的可利用性。
在本博客中,我们将演示如何利用 Windows Server 2025上的 CVE-2024-38077 进行预认证 RCE 攻击,绕过所有现代缓解措施,在最新的 Windows Server 上实现零点击 RCE。是的,你没听错,只需利用一个漏洞,你无需任何用户交互即可实现此目的。
【远程桌面许可 (RDL) 服务】
远程桌面许可服务是 Windows Server 的一个组件,用于管理和颁发远程桌面服务的许可证,确保对远程应用程序和桌面的安全且合规的访问。
RDL 服务广泛部署在启用了远程桌面服务的机器上。默认情况下,远程桌面服务仅允许同时使用两个会话。要启用多个同时会话,您需要购买许可证。RDL 服务负责管理这些许可证。RDL 被广泛安装的另一个原因是,在Windows 服务器上安装远程桌面服务 (3389) 时,管理员通常会勾选安装 RDL 的选项。这导致许多启用了 3389 的服务器也启用了 RDL 服务。
在审计RDL服务之前,我们进行了网络扫描,以确定RDL服务在互联网上的部署情况。我们发现至少有17万个活跃的RDL服务直接暴露在公共互联网上,而内部网络中的数量无疑要大得多。此外,RDL服务通常部署在关键业务系统和远程桌面集群中,因此RDL服务中的预认证RCE漏洞对网络世界构成了重大威胁。
【CVE-2024-38077:一个简单的堆溢出漏洞】
终端服务器授权程序旨在管理将任何用户或设备连接到服务器所需的终端服务 CAL。在CDataCoding::DecodeData过程中,会分配一个固定大小的缓冲区(21 字节),然后使用该缓冲区计算并填充用户控制的长度缓冲区,从而导致堆溢出。
这是调用堆栈和伪代码:
windbg
0:012> k
# Child-SP RetAddr Call Site
00 000000b9`d2ffbd30 00007fff`67a76fec lserver!CDataCoding::DecodeData
01 000000b9`d2ffbd70 00007fff`67a5c793 lserver!LKPLiteVerifyLKP+0x38
02 000000b9`d2ffbdc0 00007fff`67a343eb lserver!TLSDBTelephoneRegisterLicenseKeyPack+0x163
03 000000b9`d2ffd7d0 00007fff`867052a3 lserver!TLSRpcTelephoneRegisterLKP+0x15b
04 000000b9`d2fff0c0 00007fff`8664854d RPCRT4!Invoke+0x73
05 000000b9`d2fff120 00007fff`86647fda RPCRT4!NdrStubCall2+0x30d
06 000000b9`d2fff3d0 00007fff`866b7967 RPCRT4!NdrServerCall2+0x1a
07 000000b9`d2fff400 00007fff`86673824 RPCRT4!DispatchToStubInCNoAvrf+0x17
08 000000b9`d2fff450 00007fff`866729e4 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x194
09 000000b9`d2fff520 00007fff`86688d4a RPCRT4!RPC_INTERFACE::DispatchToStub+0x1f4
0a 000000b9`d2fff7c0 00007fff`86688af1 RPCRT4!OSF_SCALL::DispatchHelper+0x13a
0b 000000b9`d2fff8e0 00007fff`86687809 RPCRT4!OSF_SCALL::DispatchRPCCall+0x89
0c 000000b9`d2fff910 00007fff`86686398 RPCRT4!OSF_SCALL::ProcessReceivedPDU+0xe1
0d 000000b9`d2fff9b0 00007fff`86697f4c RPCRT4!OSF_SCONNECTION::ProcessReceiveComplete+0x34c
0e 000000b9`d2fffab0 00007fff`840377f1 RPCRT4!CO_ConnectionThreadPoolCallback+0xbc
0f 000000b9`d2fffb30 00007fff`867f7794 KERNELBASE!BasepTpIoCallback+0x51
10 000000b9`d2fffb80 00007fff`867f7e37 ntdll!TppIopExecuteCallback+0x1b4
11 000000b9`d2fffc00 00007fff`85b11fd7 ntdll!TppWorkerThread+0x547
12 000000b9`d2ffff60 00007fff`8683d9c0 KERNEL32!BaseThreadInitThunk+0x17
13 000000b9`d2ffff90 00000000`00000000 ntdll!RtlUserThreadStart+0x20
C
void __fastcall CDataCoding::SetInputEncDataLen(CDataCoding *this)
{
// ...
dword_1800D61D0 = 35;
v1 = log10_0((double)dword_1800D61C8) * 35.0;
v2 = v1 / log10_0(2.0);
v3 = (int)v2 + 1;
v4 = 0;
if ( v2 <= (double)(int)v2 )
v3 = (int)v2;
LOBYTE(v4) = (v3 & 7) != 0;
LODWORD(dwBytes) = (v3 >> 3) + v4; // dwBytes is a fixed value 21
}
__int64 __fastcall CDataCoding::DecodeData(
CDataCoding *this,
const unsigned __int16 *a2,
unsigned __int8 **a3,
unsigned int *a4)
{
// ...
v4 = 0;
v8 = 0;
if ( a3 )
{
// dwBytes is a global variable with value 21
v9 = dwBytes;
*a3 = 0i64;
*a4 = 0;
ProcessHeap = GetProcessHeap();
v11 = (unsigned __int8 *)HeapAlloc(ProcessHeap, 8u, v9);
v12 = v11;
if ( v11 )
{
memset_0(v11, 0, (unsigned int)dwBytes);
while ( *a2 )
{
// Str is BCDFGHJKMPQRTVWXY2346789
// a2 is user-controlled buffer
v13 = wcschr_0(Str, *a2);
if ( !v13 )
{
v4 = 13;
v18 = GetProcessHeap();
HeapFree(v18, 0, v12);
return v4;
}
// here change the integer a2 from base 24 to base 10
// but does not check the length of a2
v14 = v13 - Str;
v15 = v12;
v16 = (unsigned int)(v8 + 1);
do
{
v17 = dword_1800D61C8 * *v15 + v14;
*v15++ = v17;
LODWORD(v14) = v17 >> 8;
--v16;
}
while ( v16 );
if ( (_DWORD)v14 )
v12[++v8] = v14;
++a2;
}
*a4 = dwBytes;
*a3 = v12;
}
else
{
return 8;
}
}
else
{
return 87;
}
return v4;
}
}
【POC】
这里我们只是演示了漏洞利用。详细的技术解释将在本系列的后续博客文章中。这里的 Python 代码实际上是伪代码。你甚至无法用这个伪代码触发漏洞,更不用说利用它了。这足以证明漏洞的严重性,也为防御者提供了足够的时间,让他们能够在有人真正弄清楚如何利用漏洞之前采取行动。
适用于:Windows Server 2025 标准版本 24H2(26236.5000.amd64fre.ge_prerelease.240607-1502lserver.dll(10.0.26235.5000)
https://github.com/CloudCrowSec001/CVE-2024-38077-POC/blob/main/CVE-2024-38077-poc.py
【讨论POC】
该漏洞利用的 POC 在 Windows Server 2025 上的成功率超过 95%。考虑到服务崩溃后会重新启动,不需要两次泄露模块基址,最终的成功率可以更高(接近 100%)。
此 POC 将在 Windows Server 2025 上在 2 分钟内完成。但是我们这里的堆整理技术是使用 Windows Server 2025 中引入的新 LFH 缓解措施的未优化版本。我们很懒,实际上并没有完全逆转 Windows Server 2025 中的段堆机制,所以我们的堆整理只是一种启发式解决方案。它一点也不优雅。当然,你必须可以对其进行优化,以使漏洞在 Windows Server 2025 上运行得更快。
对于 Windows Server 2000 到 Windows Server 2022,利用此漏洞会更快,因为缓解措施较少。为简单起见,POC 将加载远程 DLL。但您可以让它在 RDL 进程中运行任意 shellcode。这将使其更加隐蔽。
在 Windows Server 2025 之前的版本中利用此漏洞应该更容易和更有效,但当然,你需要调整代码和偏移量。漏洞可以在 Windows Server 2000到 Windows Server 2025上构建。这里我们只在 2025 进行演示,因为 Windows Server 2025 是最新和最安全的Windows Server 。而且它仍处于预览阶段,因此 POC 不会对世界造成危害。如果要避免偏移量问题以使漏洞利用更加通用,动态搜索是可能的,但你需要将其替换为更高效的内存读取原语以使漏洞利用更加高效。
这里我们做了一个负责任的披露。为了进一步防止这个 POC 被滥用,这里发布的 POC 只是伪代码,并且是未优化的版本,其中的一些关键部分被隐藏了。但伪代码中的信息足以让研究人员检测和阻止利用。
【演示】
视频链接地址:
https://www.youtube.com/watch?v=OSYOrRS2k4A&t=8s
【时间线】
2024年5月1日
向Microsoft报告此案例
2024年7月1日
告诉微软此案可利用
2024年7月9日
修复为CVE-2024-38077(微软将其标记为不太可能被利用)
2024年8月2日
将本文发送至 Microsoft
2024年8月9日
微软尚未对本文做出任何回应
2024年8月9日
文章发布
【讨论】
在本文中,我们将演示如何利用单个漏洞绕过所有缓解措施,并在被认为是最安全的 Windows Server 2025 上实现预身份验证远程代码执行 (RCE) 攻击。这在 2024 年似乎很荒诞,但这是事实。尽管微软几十年来对 Windows 进行了各种防御,并且多年来我们都没有在 Windows 中看到预身份验证 0-click RCE,但我们仍然可以利用单个内存损坏漏洞来完成整个攻击。看起来,具有“下一代安全改进”的系统这次无法阻止 30 年前同样的旧内存利用。
本文的目的是提醒用户尽快更新系统以修复漏洞。
这个组件中其实还有更多的利用,记住我们已经报告了 56 个案例(虽然微软 SRC 合并了我们的许多案例,这很烦人)。有兴趣的研究人员可以尝试弄清楚。
这是本系列的第一篇博文。有关更多漏洞、更多漏洞、与 Microsoft SRC 合作的痛苦与收获等,我们可能会在本系列的后续博文中讨论。
三、事件分析
不知道大家读完原文之后是什么感觉,笔者是体会到了原文作者对微软的深深恶意。核心原因是作者把大量漏洞报送给微软后,微软对其提交的漏洞进行了合并,并“轻描淡写”的进行了补丁升级,在补丁上也把该漏洞标记为了“不太可能被利用”,对作者本人也并未做出任何回应。这一行为明显触及了技术宅的底线,一气之下作者选择了将其公布。在crowdstrike引发了windows蓝屏事件后,又爆出了这个惊天大瓜,难免会引起唏嘘,对微软有不小的冲击。
微软给的官方补丁链接为:
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-38077
这里确实将该漏洞标记为了“不太可能利用”,刺激到了作者。
另外文中反复强调,放出来的POC是“伪代码”,我们也第一时间对该代码进行了验证,发现确实不能直接利用,截至发稿前正在对其核心内容进行调试。网传的POC和漏洞检测工具更是错综复杂,提醒大家一定要留个心眼,不要人云亦云。
四、漏洞影响范围
从目前得到的信息来看,触发该漏洞需要两个条件:
windows版本:
Windows Server 2000 - Windows Server 2025
需要开启服务:
Windows Remote Desktop Licensing(RDL)Service
这里容易引起大家误解的就是这个RDL服务了,容易和我们常见的RDP产生混淆,也是为什么这个洞刚爆出来大家一致认为是“核弹级”的,能够比肩“永恒之蓝”的原因。实际上这个服务默认不会自动安装,需要额外安装才会生效,一般出现在企业环境中,个人用户基本不会安装这个服务。我们大致总结了下RDL和RDP的区别,以遍大家能更客观的评估这个漏洞的影响范围。
【RDP】
定义与功能:
RDP,即远程桌面协议,是微软开发的一种网络协议,用于在图形用户界面(GUI)中提供远程连接功能。它允许用户通过网络连接到其他计算机的桌面,以便进行操作和管理。RDP的默认端口是3389。
应用场景:
RDP广泛用于远程管理服务器、远程办公、技术支持等场景,允许用户通过网络在不同地点安全地访问另一台计算机。
【RDL】
定义与功能:
RDL,即远程桌面许可服务,负责管理和颁发许可证。它是Windows Server角色之一,通常用于Windows Server系统。在启用远程桌面服务(RDS)的环境中,RDL确保服务器拥有足够的授权许可证,以便允许多个用户或设备通过RDP同时连接到该服务器。当客户端尝试通过RDP连接到具有远程桌面服务的服务器时,RDL会验证并分配适当的许可证,以确保用户遵循许可协议。启用RDL服务时会随机开启一个RPC的高端口,端口号通常在49152到65535之间。
应用场景:
RDL一般出现在企业环境中,特别是当使用Windows Server进行远程桌面会话主机(Remote Desktop Session Host,RDSH)或虚拟桌面基础架构(VDI)时。它对用户数量和会话数量的管理至关重要。
【主要区别】
目的:
RDP的主要目的是提供连接和交互功能,允许用户访问和使用远程计算机的桌面。
RDL的主要目的是管理许可证,确保连接次数在合法范围内,并控制同时允许的用户或设备数量。
技术层面:
RDP是一个协议,关注的是数据的传输和连接的建立,它是直接影响用户体验的部分。
RDL是一种服务,确保合适的许可证可用并管理连接的合规性,它在后台运行,不会直接影响用户的操作体验。
使用场景:
RDP可用于任何想要远程连接到Windows计算机的用户,不管是在个人设备还是在网络环境中。
RDL则更多应用于企业环境中,特别是在需要高密度并发用户的远程桌面服务中。
综上所述,RDP负责实现远程连接和用户交互,而RDL则负责管理连接的许可证和合规性。RDL主要是确保远程桌面服务在合规的用户和会话数下运行,通俗来讲,当某台服务器需要建立多个RDP连接时才会考虑开启这个服务,这个服务并不是默认加载的,需要手动安装才能生效。
从公布的“伪poc”来看,整个漏洞的检测逻辑是首先连接rpc的135端口,查询rdl服务开启的rpc端口,然后再连接rdl服务的rpc端口,访问提供的认证功能,触发漏洞。
rdl开启的rpc端口:
服务器对应的dll文件:
从www.daydaymap.com上大网测绘的数据可以看出,整个互联网上开放RDP服务的资产有近1700W个, 而互联网上RDL的资产仅有17W个(数据来源于原文作者),占比仅为1%。目前我们还正在整理互联网漏洞验证的POC细节,后续会对互联网上受影响的资产做更全面的摸排。从公开的数据已经可以看出,该漏洞的覆盖范围实际上很有限,并不是传闻中的“开机就能打”、“有远程连接服务就能打”或者“能探测到开放3389端口就能打”。与其说是RDP的漏洞,不如描述成RDL或者RPC的漏洞更为合适。
尽管如此,这也并不意味着这是一个很鸡肋的漏洞。一是因为内网资产里使用远程桌面服务的资产会远多于互联网。另外,一些集权系统如堡垒机、域控等为了对RDP连接数做有效管理和控制,更容易开启RDL服务,因此受到该漏洞影响的资产绝大多数是管理员的核心资产,从这一点上更需要引起大家的关注。我们已经发现很多堡垒机默认就会开启这个服务,需要引起大家的重视。
五、漏洞修复建议
微软已发布该漏洞的官方补丁,下载并安装相关补丁即可。对于无法安装补丁的情况,建议采取以下缓解措施:
1、如非必要,关闭Remote Desktop Licensing服务。
2、注意:此操作将影响远程桌面授权认证和分发,可能导致远程桌面出现问题影响正常业务或降低远程桌面安全性。同时,微软公告中提出:即便采取了上述缓解措施,微软仍强烈建议尽快修复漏洞以全面防护系统。
另外目前正值攻防演练期间,往上会流传大量的“检测工具”,现已发现一些恶意样本在互联网上流传,大家一定要注意识别。