Windows中错误报告机制导致的提权漏洞(CVE-2019-0863)

在2018年12月,一个名为“SandboxEscaper”的黑客公开了一个Windows Error Reporting(WER)组件中的0day漏洞。而根据他所提供的信息,我又发现了另一个0day漏洞,可被用于非法提升系统权限。根据微软方面的说法,已有攻击者利用这个漏洞进行攻击,但直到2019年5月该漏洞补丁才发布。

那么,这个漏洞的原理是啥呢?

微软的又一次失误

Windows Error Reporting工具是一个灵活的基于事件的反馈架构,旨在收集有关Windows的软硬件错误的信息,并将这些信息报告给Microsoft,好为用户提供可用的解决方案。

例如,当Windows系统崩溃或发生故障,则会生成一个错误报告并存储在WER报告队列目录下(C:\ProgramData\Microsoft\Windows\WER\ReportQueue),其中每个报告都有自己的子目录和一个存储相关元数据的名为report.wer的INI文件。为了使所有进程都能上报系统错误信息,所有用户都可以对reportQueue目录进行写入,具体如下所示:

生成报告后,接下来就是将其发送给Microsoft以进行进一步分析。此交互流程可以通过多种方式触发,其中一种就是使用名为Windows Error Reporting\QueueReporting的计划任务。而从安全角度来看,此计划任务很有趣,因为:

  • 它以system权限运行,这就非常敏感了。
  • 它可以根据需求触发。
  • 它涉及了一个exe文件wermgr.exe,以及一个参数-upload

在计划任务触发后,wermgr.exe与等待处理的报告文件和目录进行交互。它会读取、解析这些文件,将它们复制到其他目录,或是直接删除。但最重要的是,现在一个高权限的exe会处理任何用户都可以写入的文件。如果这中间流程存在问题,可能会导致一些严重的安全漏洞。

滥用文件链接

Windows支持不同类型的文件链接,它们可将某处的文件或目录指向其他的文件和目录,简单来说,就是会将用户重定向到目标路径。从安全的角度来看,文件链接很容易造成权限漏洞,因为用户可以将某些文件链接到他们没有写权限的文件或目录。

下面的示例描述了不具有kernel32.dll写入权限的用户是如何创建c:\temp\Dir\\x.dll和C:\Windows\System32\kernel32.dll之间的链接的。这样有可能使黑客可以读、写甚至删除敏感的系统文件。

漏洞信息

简而言之,黑客可以利用WER的system权限去更改任意文件。通过上述文件的链接,将WER目录中的文件链接到计算机上其他目录的文件,从而借助计划任务的system权限帮助自己提升权限。

以下是完整的漏洞利用场景:

  • Step 1:wermger.exe逐个解析报告目录中的所有文件,并将其提交给Microsoft。
  • Step 2:当wermger.exe检测到名为Report.wer的被损坏的INI文件时,会进行一系列处理,最终会将其删除。但在删除前,它会改变文件的访问控制权限,以方便将其删除。
  • 漏洞利用点:黑客主要是利用wermger.exe读取文件的访问控制权限和改变其权限之间的短暂机会。如果攻击者创建一个错误报告与系统上其他文件之间的链接,则在修改访问控制的权限后,wermgr.exe就会错误地修改其他文件的权限。

Step 1:

命令wermgr.exe -upload所做的第一件事就是调用wermgr!DoCoreUpload函数,它会列出reportQueue下的所有子目录,并读取错误报告将其提交给Microsoft:

int64 DoCoreUpload(/* ... */) {
/* ... */
Ret = WerpSubmitReportFromStore(ReportPath, /* ... */);
if (Ret >= 0) {
/* Report successfully uploaded */
} else {
if (Ret == ERROR_FILE_CORRUPT) {
DeleteCorruptedReportFromStore(ReportPath);
}
}
}

Step 2:

当wermgr.exe遇到已损坏的名为report.wer的INI文件时,它会更改其访问控制权限以便稍后删除它。更具体地说:

1.首先,wermgr!DeleteCorruptedReportFromStore会列出子目录下的所有文件;

2.接着,wermgr!PreparePathForDeletion会修改每个文件的权限。这就是漏洞原理所在!因为此函数会使用kernel32!GetFileSecurity读取文件的安全描述符,并利用kernel32!SetFileSecurity将其设置为可删除。

int64 PreparePathForDeletion(wchar_t* FileName) {

PSECURITY_DEsc riptOR SecurityDesc riptor = NULL;

DWORD BytesRead = 0;

PDACL Dacl = NULL;

/* ... */

if ( !GetFileSecurity(FileName,

DACL_SECURITY_INFORMATION,

NULL, 0, &BytesRead) ) {

/* ... */

return;

}

SecurityDesc riptor = new BYTE[BytesRead];

if ( !GetFileSecurity(FileName,

DACL_SECURITY_INFORMATION,

SecurityDesc riptor,

BytesRead, &BytesRead) ) {

/* ... */

return;

}

if ( GetSecurityDesc riptorDacl(SecurityDesc riptor,

&DaclPresent,

&Dacl, &DaclDefaulted) )

{

/* ... */

HANDLE TokenHandle = NULL;

PACL NewAcl = NULL;

EXPLICIT_ACCESS ExplicitAccess = {0};

/* ... */

LPVOID UserName = new BYTE[/* ... */];

GetTokenInformation(TokenHandle, TokenUser,

UserName, &BytesRead);

ExplicitAccess.Trustee.ptstrName = UserName;

ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_NAME;

ExplicitAccess.grfAccessMode = GRANT_ACCESS;

ExplicitAccess.grfAccessPermissions = DELETE | /* ... */;

/* ... */

SetEntriesInAcl(1, &ExplicitAccess, Dacl, &NewAcl);

InitializeSecurityDesc riptor(&SecurityDesc riptor, 1);

SetSecurityDesc riptorDacl(&SecurityDesc riptor, 1, NewAcl, 0);

SetFileSecurity(FilePath, DACL_SECURITY_INFORMATION,

&SecurityDesc riptor);

}

}

不过,在特定的时间创建文件链接较为困难,这可能需要一次又一次的尝试。攻击者在实际操作中很可能以可执行文件(dll、exe或脚本)为目标,尝试使用恶意文件覆盖它们,最后等待系统自动执行。

本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场

来源:https://nosec.org/home/detail/2742.html

原文:https://unit42.paloaltonetworks.com/tale-of-a-windows-error-reporting-zero-day-cve-2019-0863/

白帽汇从事信息安全,专注于安全大数据、企业威胁情报。

公司产品:FOFA-网络空间安全搜索引擎、FOEYE-网络空间检索系统、NOSEC-安全讯息平台。

为您提供:网络空间测绘、企业资产收集、企业威胁情报、应急响应服务。

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();