CVE-2021-1648漏洞剖析:绕过补丁的提权与信息泄露攻击链

本文深度分析了微软在2021年1月修复的splwow64服务漏洞CVE-2021-1648,详细描述了如何通过命令0x6A绕过补丁引入的句柄检查函数,以及如何利用未检查的源地址实现任意地址读取。文章还揭示了两个额外的绕过“UMPDStringPointerFromOffset”和“UMPDPointerFromOffset”检查函数的安全案例。

背景

在2021年1月的补丁星期二,MSRC修复了splwow64服务中的一个漏洞,被分配为CVE-2021-1648(亦称为CVE-2020-17008)。该漏洞合并了我提交的两个绕过CVE-2020-0986补丁的有趣案例,其中一个也被Google Project Zero发现。

该漏洞原计划在2020年10月修复,但MSRC似乎在服务中发现了其他更严重的安全问题,因此将补丁推迟了四个月。

绕过FindDriverForCookie和FindPrinterHandle

CVE-2020-0986被修复后,我对splwow64和gdi32full进行了快速的bindiff分析,发现补丁后增加了两个检查。

第一个是微软增加了两个打印机句柄(或称cookie?)检查函数,名为FindDriverForCookieFindPrinterHandle,它们将检查存储在一个全局变量中的打印机驱动句柄。

另一个是MSRC增加了两个指针检查函数UMPDStringPointerFromOffsetUMPDPointerFromOffset,以检查指针是否有效。

首先,我不知道微软增加FindDriverForCookieFindPrinterHandle的目的,也许并不是为了缓解措施?快速审查后,我发现有一个命令0x6A可以设置打印机句柄,我们可以控制该句柄在服务的全局变量中的值,从而绕过这两个检查函数。

通过调用命令0x6A,函数bAddPrinterHandle会将打印句柄添加到存储在全局变量|qword_1800EABA0|中的驱动堆上。

这样,我们就可以在调用命令0x6D时轻松绕过打印机句柄检查,并命中漏洞代码。

CVE-2021-1648:任意地址读取

让我们谈谈信息泄露。CVE-2021-1648包含一个任意地址读取的信息泄露漏洞。

命令0x6D的代码太长,我不会在博客中全部贴出。简而言之,它会检查memcpy的目标地址是否在“有效”范围内(即|v6+0x58|的范围),但源地址|v57|未被检查,因此我们可以读取任意地址。

调用栈:

1
2
3
4
5
6
7
8
gdi32full!GdiPrinterThunk+0x1a73
splwow64+0x78ab
splwow64+0x84de
splwow64+0x9f28
ntdll!RtlDeleteCriticalSection+0x363
ntdll!RtlInitializeResource+0xce4
KERNEL32!BaseThreadInitThunk+0x14
ntdll!RtlUserThreadStart+0x21

CVE-2021-1648的另外两个案例

我向MSRC报告的另外两个案例是关于绕过偏移检查函数UMPDStringPointerFromOffsetUMPDPointerFromOffset的。我认为MSRC在这两个函数的范围检查上犯了一个错误。

Splwow64是一个特殊的服务,在x86-64 Windows操作系统中兼容x86,因此它总是分配32位的堆。但在CVE-2020-0986的补丁中,UMPDStringPointerFromOffsetUMPDPointerFromOffset只检查偏移量和|portview+offset|是否小于0x7fffffff。

然而,在splwow64服务中,许多堆甚至栈都分配在低地址。因此,通过占用splwow64服务中的某些重要堆或栈来进行攻击是可能的。我在报告中建议MSRC检查指针范围是否在portview段内,而不是0x7fffffff。

两个案例的崩溃转储:

1
2
gdi32full!UMPDStringPointerFromOffset+0x12:
gdi32full!UMPDPointerFromOffset+0xa:

故事结尾

看起来微软重新设计了splwow64打印机服务,因此他们将补丁推迟了四个月。这对我来说,等待一个Windows补丁的时间真的很长。希望新的打印机服务能更安全。

时间线

  • 2020-07-27 报告给MSRC。
  • 2020-08-19 MSRC决定推迟补丁。
  • 2020-08-22 获得赏金。
  • 2021-01-13 补丁发布。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计