CVE-2023-38146:通过 Windows 主题执行任意代码

原文: CVE-2023-38146: Arbitrary Code Execution via Windows Themes

这是我在研究奇怪的 Windows 文件格式时发现的一个有趣的错误。这是一种经典的 Windows 风格漏洞,具有签名损坏、DLL 加载粗略、文件竞争、cab 文件和 Web 愚蠢标记等特征。这也是我自 2022 年 4 月离开微软以来第一次向 MSRC Windows 漏洞赏金提交。

按照命名漏洞的伟大传统,我亲切地将这个命名为 ThemeBleed(目前还没有徽标,但我正在接受提交。)

总的来说,发现并 PoC 这个漏洞非常有趣,MSRC 的响应速度和判断赏金的速度令人难以置信:

以下是我发送给 Microsoft 的报告的稍微修改版本。报告之后是时间表和我的修复说明。

概述

Windows 11 上存在一系列问题,这些问题可能导致用户加载 .theme 文件时执行任意代码。

漏洞细节

1. 背景

在 Windows 上,.theme 文件允许自定义操作系统外观。 .theme 文件本身是 ini 文件,其中包含配置详细信息。单击 Windows 11 上的 .theme 文件将调用以下命令:

1
"C:\WINDOWS\system32\rundll32.exe" C:\WINDOWS\system32\themecpl.dll,OpenThemeAction <theme file path>

此漏洞专门涉及 .msstyles 文件的处理。这些是 PE (DLL) 文件,其中包含主题中使用的图标等资源,但(应该)不包含任何代码。 .msstyles 文件可以通过以下方式在 .theme 文件中引用:

1
2
[VisualStyles]
Path=%SystemRoot%\resources\Themes\Aero\Aero.msstyles

打开 .theme 文件时,.msstyles 文件也会被加载。

2. “999版本”检查

当加载.msstyles文件时,uxtheme.dll中的 LoadThemeLibrary 将检查主题的版本。它将通过从二进制文件加载名为 PACKTHEM_VERSION 的资源来完成此操作。如果它读取的版本是999,它将调用另一个函数 ReviseVersionIfNecessary。该函数的反编译版本以及相关部分的注释如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
__int64 __fastcall LoadThemeLibrary(const WCHAR *msstyles_path, HMODULE *out_module, int *out_version)
{
HMODULE module_handle;
signed int result;
int version;
signed int return_val;
unsigned int resource_size;
__int16 *version_ptr;

if ( out_version )
*out_version = 0;
module_handle = LoadLibraryExW(msstyles_path, 0, 2u);
if ( !module_handle )
return (unsigned int)MakeErrorLast();
result = GetPtrToResource(
module_handle,
L"PACKTHEM_VERSION",
(const unsigned __int16 *)1,
(void **)&version_ptr,
&resource_size); // !!! [1] version number is extracted from resource "PACKTHEM_VERSION"
if ( result < 0 || resource_size != 2 )
goto LABEL_22;
version = *version_ptr;
if ( out_version )
*out_version = version;
return_val = -2147467259;
if ( version >= 4 )
{
if ( version > 4 )
result = -2147467259;
return_val = result;
}
if ( return_val < 0 && (_WORD)version == 999 ) // !!! [2] special case for version 999
{
resource_size = 999;
return_val = ReviseVersionIfNecessary(msstyles_path, 999, (int *)&resource_size); // !!! [3] call to `ReviseVersionIfNecessary`
...
}

3. ReviseVersionIfNecessary 中的检查时间和使用时间允许绕过签名

上一步调用的 ReviseVersionIfNecessary 函数执行多个操作。给定 .msstyles 文件的路径,它将执行以下操作:

  1. _vrf.dll.msstyles 所在文件路径组合成一个新的路径

  2. 检查这个新的 _vrf.dll 文件是否存在。如果没有,直接退出

  3. 打开 _vrf.dll 文件

  4. 验证 _vrf.dll 文件的签名,如果无效,则直接退出

  5. 关闭 _vrf.dll 文件

  6. 加载 _vrf.dll 文件,并调用函数 VerifyThemeVersion

其目标似乎是尝试安全地加载签名的 DLL 并调用函数。然而,这种实现是有缺陷的,因为 DLL 在步骤 5 中验证签名后关闭,然后在步骤 6 中通过调用 LoadLibrary 加载 DLL 时重新打开。这在这两个步骤之间提供了一个竞争窗口,攻击者可以用未签名的恶意文件替换已验证签名的 _vrf.dll 文件。然后该恶意 DLL 将被加载并执行。

4. Mark-of-the-Web(MOTW)绕过

如果用户下载 .theme 文件,则在启动该文件时,由于该文件上存在 Mark-of-the-Web,他们将收到安全警告。事实证明,可以通过将 .theme 文件打包在 .themepack 文件中来绕过这个问题。

.themepack 文件是包含 .theme 文件的 cab 文件。打开 .themepack 文件时,将加载包含的 .theme 文件。当使用 Mark-of-the-Web 打开 .themepack 文件时,不会显示任何警告,因此通常会看到的警告被绕过。

概念验证

我针对这个问题开发了一个PoC。 PoC 由两个组件组成:一个在攻击者计算机上运行的 SMB 服务器可执行文件,以及一个在目标计算机上打开的 .theme 文件。

为此,我选择使用攻击者控制的 SMB 服务器,因为 .theme 文件可能指向远程 SMB 共享上的 .msstyle 路径。由于 SMB 共享是由攻击者控制的,因此当客户端首次请求检查签名时,它可以通过返回有效签名的文件来轻松利用 ReviseVersionIfNecessary 中的 TOCTOU 错误,然后,当客户端加载 DLL 时,就会出现恶意攻击。

PoC 可以在这里找到:https://github.com/gabe-k/themebleed

环境准备

要运行 PoC,您将需要两台机器,一台将运行 SMB 服务器的攻击者机器,以及一台将在其中加载 .theme 文件的目标机器。以下是各机器的要求:

攻击者机器

  • Windows 10 或 11
  • 禁用 “Server” 服务以释放 SMB 端口(禁用并重新启动,不要只是停止该服务)
  • 最新的 .Net 框架
  • 接入到互联网,能直接访问

目标主机

  • 最新版本的windows11

重现步骤

  1. 通过运行以下命令创建 .theme 文件:themebleed.exe make_theme <attacker machine ip>exploit.theme

  2. 在攻击者机器上运行:themebleed.exe server

  3. 在目标机器上打开 exploit.theme

这应该会导致计算器在目标计算机上打开。这表明任意代码已被执行。

总结

这是一个可靠的漏洞,从加载主题到下载和执行代码,都不会损坏内存。此外,此漏洞似乎是新漏洞,仅存在于 Windows 11 中。我请求考虑将此提交视为赏金。

为了修复这个漏洞,我建议:

  • 完全删除“版本 999”功能,但我不完全确定它的预期用途是什么。

  • 以 Windows 验证其他代码的标准方式签署和验证 _vrf.dll 二进制文件,而不是容易受到此类竞争条件影响的代码。

  • 禁止从主题文件中的远程共享加载资源。

  • 将 Web 标记警告添加到 .themepack 文件。

参考

A. Details about the Mark-of-the-Web (MOTW) https://nolongerset.com/mark-of-the-web-details/

B. Save Custom Theme in Windows 11 https://www.elevenforum.com/t/save-custom-theme-in-windows-11.9908/

C. 如何监控获取到双击文件的信息? 可以通过 ProcExplorer.exe 设置 Path 过滤Contains 你的theme文件名称即可,如下图:


CVE-2023-38146:通过 Windows 主题执行任意代码
https://xxxxnnxxxx.github.io/2023/09/17/CVE-2023-38146/
作者
xxxxnnxxxx
发布于
2023年9月17日
许可协议