概述
2023 年 3月补丁星期二解决的漏洞中,有一个是Outlook 的一个严重漏洞,编号为CVE-2023-23397,该漏洞被 Forest Blizzard 在野利用,微软已将其确定为俄罗斯国家支持的威胁行为者。2023 年 12 月,微软与波兰网络司令部 (DKWOC) 联合发布消息称,他们发现同一威胁行为者最近试图利用该漏洞。该漏洞允许攻击者强迫 Outlook 客户端连接到攻击者的服务器。作为此连接的一部分,客户端会将其 NTLM 凭据发送给攻击者,攻击者随后可以离线破解这些凭据,或者在中继攻击中使用它们。此漏洞可以通过互联网远程利用,无需任何用户交互(零点击)。
在针对此漏洞的补丁发布后,我们发现了一种绕过方法,我们在之前的博客文章中描述了这种方法。此绕过方法已在 2023 年 5 月的补丁星期二修复。在那篇文章中,我们建议 Microsoft 删除被滥用的功能,因为它引入了一个庞大而复杂的攻击面。由于该功能仍保留在 Outlook 中,我们决定进一步调查。
最终,我们能够在 Outlook 上实现完整的 RCE 漏洞链。我们发现了原始 Outlook 漏洞的另一个绕过方法 — 这种方法再次允许我们强制客户端连接到攻击者控制的服务器并下载恶意声音文件。然后,我们设法在 Windows 媒体解析库中找到一个漏洞,该库用于处理和播放任何音频文件,特别是 Outlook 的通知声音。攻击者将这些漏洞串联起来,就可以在易受攻击的 Outlook 客户端上实现零点击 RCE。
本系列博文分为两部分,将介绍我们为发现这两个漏洞而进行的研究。第一部分将重点介绍之前的绕过方法和新的绕过方法。在第二部分中,我们将描述我们发现的媒体解析漏洞。
原始漏洞
当攻击者发送包含带有自定义通知声音的提醒的电子邮件时,就会触发 3 月份修补的 Outlook 漏洞。攻击者使用扩展的MAPI属性PidLidReminderFileParameter将此自定义声音指定为路径。攻击者可以指定 UNC 路径,该路径会导致客户端从任何 SMB 服务器检索声音文件。作为与远程 SMB 服务器连接的一部分,Net-NTLMv2 哈希会在协商消息中发送(图 1)。图1:NTLM凭证的强制执行
为了解决这个问题,代码现在调用*MapUrlToZone*将路径分类为内联网、本地或互联网。如果 URL 指向互联网上的资源,则使用默认提醒声音,而不是自定义提醒声音。
寻找绕过方法
采取缓解措施后,我们问自己是否有可能绕过它。
在此上下文中,绕过意味着一条路径既能通过本地性测试,又能被 Outlook 用于从远程位置下载声音文件。换句话说,我们需要找到一条*MapUrlToZone*认为是非互联网的路径,而*CreateFile*会将其视为互联网域。
为了找到这样的绕过方法,我们需要充分了解函数的内部工作原理以及作为路径解析的一部分所完成的操作。
Windows 路径和 URL
Windows 中有许多不同类型的DOS 路径,并且已经对它们及其转换为 NT 路径进行了大量研究。我们不会在这里介绍不同的 Windows 路径类型;James Forshaw 的博客文章详细介绍了这个主题。
让我们回到我们感兴趣的函数。CreateFile接收 Windows 路径;MapUrlToZone (正如其名称所**暗示的)可以传递 URL 或路径。要找到绕过方法,我们首先需要了解每个函数(或两者)支持的路径类型。
注意:CreateFile和MapUrlToZone本身不处理路径;相反,它们使用其他 WinAPI 函数来实现此目的。为了简洁起见,我们将使用CreateFile和MapUrlToZone来指代其底层路径解析函数。
创建文件 | 映射网址到区域 | |
---|---|---|
RtlPathTypeUncAbsolute | ✔ | ✔ |
RtlPathTypeDriveAbsolute | ✔ | ✔ |
RtlPathTypeDriveRelative | ✔ | ✔ |
RtlPathTypeRooted | ✔ | ✘ |
RtlPathTypeRelative | ✔ | ✘ |
RtlPathType本地设备 | ✔ | ✔ |
RtlPathTypeRootLocalDevice | ✔ | ✘ |
方案(file://、http://) | ✘ | ✔ |
表1: CreateFile与MapUrlToZone路径能力对比图
如表 1 所示,这两个函数仅支持四种路径类型:RtlPathTypeUncAbsolute、RtlPathTypeDriveAbsolute、RtlPathTypeDriveRelative和RtlPathTypeLocalDevice。
首次尝试
第一次尝试绕过是使用绝对 UNC 路径 ( RtlPathTypeUncAbsolute )。图 2 详细说明了路径的结构。图 2:绝对 UNC 路径及其组成部分
那么Windows如何知道路径部分从哪里开始呢?表2显示了相关代码(RtlGetFullPathName_Ustr)。
case RtlPathTypeUncAbsolute:
SeperatorsFound = 0;
for ( CurrentIndex = 2; CurrentIndex < InputPathLength; ++CurrentIndex )
{
CurrentChar = InputPathString->Buffer[CurrentIndex];
if ( CurrentChar == '\' || CurrentChar == '/' )
{
SeperatorsFound++;
if ( SeperatorsFound == 2 )
break;
}
}
复制
表 2:处理 UNC 路径的RtlGetFullPathName_Ustr代码片段
我们可以看到,代码跳过了绝对 UNC 前缀(“”),然后假定路径组件从第二个路径分隔符('' 或 '/')后一个字符开始。
但是如果我们提供诸如“\localhost..Akamai.comdirfile.txt”这样的路径会发生什么? 该路径将按如下方式处理:
-
“\” 被解释为 UNC 前缀和根路径组件 -
路径部分是“localhost..Akamai.comdirfile.txt”
通常情况下,任何“..”都不能超出根路径。例如,“localhostdirectory..file.txt”将导致“localhostdirectoryfile.txt”。但是,由于在我们的示例中,“..”不是根路径的一部分,因此路径将转换为“\Akamai.comdirfile.txt”。
这意味着我们找到了一种通过删除部分路径来篡改路径的方法。
这就是CreateFile处理此路径的方式;那么**MapUrlToZone如何处理它(表 3)?它首先删除多余的反斜杠,因此它以不同的方式解释路径:
-
localhost 是服务器名称 -
.. 被忽略(因为我们不能超出服务器名称) -
Akamai.comdirfile.txt 包含路径部分
输入路径:\ localhost .. Akamai.com dir file.txt | |
---|---|
创建文件 | 映射网址到区域 |
\Akamai.comdirfile.txt | localhostAkamai.comdirfile.txt |
表3:CreateFile和MapUrlToZone的输入路径及其解析结果
对于上面看到的输出路径,MapUrlToZone返回 0(本地)。
虽然这看起来像是我们找到了绕过方法,但不幸的是,该路径无法用于触发 UNC 请求。请注意CreateFile处理的路径开头的额外斜杠- 这标志着服务器名称为空。当多个 UNC 提供程序 (MUP) 向不同的网络提供商查询它们是否可以处理这个(空的)服务器名称时,它们都返回 false - 因此不会发出任何请求。
滥用MapUrlToZone 和CreateFile处理此路径的方式之间的差异可能需要更复杂的解决方案 — 比如找到一种方法来省略额外的反斜杠,或者在 MUP 代码中找到解析不匹配。这是对未来研究的建议。
第二次尝试:绕过 #1(CVE-2023-29324)
由于使用绝对 UNC 路径实际上不起作用,我们继续研究支持 UNC 的下一个路径类型 — RtlPathTypeLocalDevice。“.UNCAkamai.comtest.wav” 是本地设备路径的一个示例。具体来说,它指向 UNC 设备名称,该名称将被重定向到 MUP 驱动程序。
正如我们之前所说,要找到绕过方法,我们需要查看路径解析过程中执行的不同操作。表 4 显示了这种差异。
创建文件 | 映射网址到区域 |
---|---|
如果 RtlPathTypeLocalDevice → 前进 4 个字符 | 如果 RtlPathTypeLocalDevice → 前进 4 个字符 |
跳过尾随空格 | |
将 '/' 转换为 '' | |
折叠重复‘’ | |
删除“.”和“..”组件 | 删除“.”和“..”组件 |
表 4:路径解析过程中完成的不同操作
我们可以看到CreateFile做了额外的操作,例如将正斜杠转换为反斜杠以及折叠重复的反斜杠。
让我们看一下利用这些差异之一的路径 — 使用额外的路径分隔符。表 5 显示了代码跳过“UNC”前缀后生成的路径。
输入路径:.UNCAkamai.comtest.wav | |
---|---|
创建文件 | 映射网址到区域 |
Akamai.com测试.wav | Akamai.com测试.wav |
表 5:跳过 UNC/ 前缀后的结果路径
注意右列中的路径。以路径分隔符开头,后跟非路径分隔符字符的路径称为根路径。MapUrlToZone使用函数IsRootedPath或IsDrivePath来确定根路径组件是否为本地。在我们的例子中,路径是根路径,因此MapUrlToZone返回本地。
CreateFile在 UNC 前缀后没有额外的路径分隔符,因此它知道正确提取域名,现在访问 Akamai.com SMB 服务器以检索 test.wav 文件。我们发现***MapUrlToZone*认为是本地路径,但*CreateFile*却不这么认为。此绕过重新启用了对 Outlook 漏洞CVE-2023-23397**的利用。
为了缓解这个问题,微软试图让这两个流程更加相似;将正斜杠转换为反斜杠和折叠重复路径分隔符的操作现在被添加到MapUrlToZone路径解析流程中。
一个想法……
在上一节中,我们注意到MapUrlToZone检查“.UNC”后面的路径组件是驱动器路径还是根路径。修复后,我们无法将此路径组件设为根路径,因为重复的路径分隔符被折叠了。但是,我们仍然可以提供驱动器路径;例如“.UNCC:Akamai.com/test.wav”。
这样做确实会导致MapUrlToZone返回 0。不幸的是,没有网络提供商能够处理带有冒号的路径,因此这种混淆对我们没有帮助。与我们第一次(失败的)尝试一样,发现 MUP 解析代码的混淆可能会导致新的漏洞。
第三次尝试:绕过 #2(CVE-2023-35384)
修复后,两个函数执行的操作几乎相同(表6)。
创建文件 | 映射网址到区域 |
---|---|
如果 RtlPathTypeLocalDevice → 前进 4 个字符 | 如果 RtlPathTypeLocalDevice → 前进 4 个字符 |
跳过尾随空格 | |
将 '/' 转换为 '' | 将 '/' 转换为 '' |
折叠重复‘’ | 折叠重复‘’ |
删除“.”和“..”组件 | 删除“.”和“..”组件 |
表 6: CreateFile和MapUrlToZone后缀执行的操作
然而,如果我们深入研究,我们可以问自己:每个函数如何确定该路径是本地设备路径?表 7 说明了每个函数中有助于确定路径类型的代码片段。
创建文件
if (IS_PATH_SEPARATOR(Path[0]) &&
IS_PATH_SEPARATOR(Path[1]) &&
(Path[2] == '.' || Path[2] == '?') &&
IS_PATH_SEPERATOR(Path[3])
return RtlPathTypeLocalDevice;
复制
映射网址到区域
!strncmp(path, "\.", 4) || !strncmp(path, "\?", 4)
复制
表 7:确定路径类型的代码片段
使用CreateFile时,路径分隔符可以是正斜杠或反斜杠;例如,“./”被视为本地设备路径。使用MapUrlToZone时,只有精确的“.”或“?”路径才被视为本地设备路径。这是一种路径类型混淆 — 我们可以让*CreateFile*将组件“./”识别为本地设备路径,而*MapUrlToZone*则不会。这种混淆导致两个函数对路径的处理不同。
考虑到这一点,让我们使用包含“令人困惑”的组件的路径:**./UNC/Akamai.com/file.wav**。
在分析此路径类型的决策时,这是MapUrlToZone的流程:
-
该路径是本地驱动器还是根路径?否 -
IsLocalDeviceUNC?否 -
PathIsUNCW?是
PathIsUNCW返回 true,因此该函数将其标记为绝对 UNC 路径,并前进两个字符以跳过 UNC 前缀“”。每个函数的输出如表 8 所示。
输入路径:./UNC/Akamai.com/file.wav | |
---|---|
创建文件 | 映射网址到区域 |
UNCAkamai.com文件.wav | ./UNC/Akamai.com/file.wav |
表 8: CreateFile和MapUrlToZone函数的路径输出
此时,CreateFile得出结论,其输出是 UNC 路径,并且 Akamai.com 是主机名。
相反,MapUrlToZone得出以下信息:
方案:file://
主持人:.(点)
路径:/UNC/Akamai.com/file.wav
绝对 URI:file://./UNC/Akamai.com/file.wav
事实证明,当绝对 URI 以“file://./”(主机为“.”)开头时,代码会将共享名称解释为 DOS 设备命名空间的一部分(图 3)。因此,“file://./UNC/”指的是 UNC 命名空间。图 3:带有点主机名的 URL(https://en.wikipedia.org/wiki/File_URI_scheme)
需要澄清的是,这两个函数都将我们的输入路径视为 UNC 路径,但类型不同:CreateFile将其视为 Windows 本地设备路径,而MapUrlToZone将其视为 URL。
此时,我们可以触发这两个函数之间的混淆。不幸的是,如果我们不采取任何技巧,MapUrlToZone仍会将 Akamai.com 解释为主机名 - 而且由于此主机名是互联网域,该函数将返回 3,因此这不是绕过。我们需要找到另一种方法来滥用解析过程。
接下来,MapUrlToZone使用名为**SetPath 的内部函数对路径组件进行操作(表 9)。
创建文件 | 设置路径 |
---|---|
如果 RtlPathTypeLocalDevice → 前进 4 个字符 | |
跳过尾随空格 | |
将 '/' 转换为 '' | |
折叠重复‘’ | |
删除“.”和“..”组件 | 删除“.”和“..”组件 |
表 9: CreateFile和SetPath之间完成的操作比较
我们再次利用了这两个函数执行的操作之间的差异。从之前的漏洞中我们知道,添加额外的斜线可能会导致绕过,因此再次尝试是有意义的。CreateFile 将 简单地删除多余的斜线。
使用 MapUrlToZone,CreateUri 返回绝对 URI “file://./UNC//Akamai.com/file.wav”。此 URI 被传递给 GetZoneFromUriInternal,后者在内部引发另一个 CreateUri 调用。
为什么这是个问题?因为 CreateUri收到一个 URL,所以它使用**PathCreateFromUrlW 将其转换回 Windows 路径 。返回的 Windows 路径是“.UNCAkamai.comtest.wav”。修复后的版本现在知道删除多余的斜线,因此可以正确理解 Akamai.com 是主机名。
这意味着我们需要更复杂地利用CreateFile 和 SetPath之间的差异 。这次,我们将利用两个差异:
-
CreateFile 折叠重复的路径分隔符。 -
CreateFile在 重复路径分隔符折叠*后* 删除了“。”和“..”组件 。
滥用这两个差异的路径是**./UNC/C://../Akamai.com/file.wav**。其处理过程详见图4的流程图。图4:两个函数解析路径的流程图
我们已经知道CreateFile的最终路径将被视为 UNC 路径。至于SetPath的输出,MapUrlToZone将使用绝对 URI file://./UNC/C:/Akamai.com/file.wav调用GetZoneFromUriInternal 。这次**PathCreateFromUrlW将此 URL 转换为 Windows 路径“.UNCC:Akamai.comfile.wav”。这是一个本地路径,因此*MapUrlToZone*返回 0(本地)。我们再次找到了一个巧妙的绕过方法!
为了解决这个问题,代码现在调用NormalizeDosDevicePrefix将斜杠转换为反斜杠,以防止在检测本地设备路径时产生混淆。
检测和缓解
微软发布了全面的指南,用于检测和缓解原始 Outlook 漏洞。根据我们的观察,所有指定的方法都适用于新漏洞,因为它们不依赖于PidLidReminderFileParameter属性中指定的 URL 。
我们建议组织使用微分段来阻止到远程公共 IP 地址的传出 SMB 连接。此外,我们建议您在环境中禁用 NTLM,或将用户添加到受保护的用户组,以防止使用 NTLM 作为身份验证机制。
阻止传出的 SMB 连接并禁用 NTLM 有助于防止凭据被盗。但是,当 SMB 请求失败时,如果启用了 WebDAV,Windows 就会转而使用 WebDAV。凭据被盗无法通过 WebDAV 进行,但仍然可以下载声音文件,这是我们 RCE 链中的第二步。
为什么现在停止?
在这篇文章中,我们详细介绍了导致发现这两种绕过方法的研究过程,包括其根本原因分析。正如我们所展示的,Windows 路径解析代码非常复杂,并且经常会导致漏洞。遇到路径处理代码的安全研究人员应该考虑它所呈现的攻击面。
除了在 Outlook 环境中绕过MapUrlToZone之外,我们不能排除这些漏洞还可能导致Mark-of-the-Web (MotW) 绕过的可能性。
除了能够泄露 NTLM 凭据之外,我们还能够下载和播放任意声音文件。现在您可以阅读本博客系列的第 2 部分,其中详细介绍了声音解析漏洞。
原文始发于微信公众号(红云谈安全):利用漏洞实现 Outlook 的 RCE:第一部分
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论