CVE-2023-36874 Windows 错误报告服务权限提升漏洞

admin 2024年5月15日21:00:18评论18 views字数 8834阅读29分26秒阅读模式

文章发表于:https://www.ch35tnut.site/zh-cn/vulnerability/cve-2023-36874-windows-error-reporting-service-eop/

基本信息

Windows error resporting service中存在权限提升漏洞,当攻击者可以创建符号链接及目录时,可以利用这个漏洞提升至SYSTEM权限。

影响版本

环境搭建

  • Windows 10 21H2 6月补丁

技术分析&调试

补丁对比

diff wercplsupport.dll,主要改了CWerComReport::SubmitReport,wercplsupport.dll是Windows error reporting 服务的主dll文件。

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

对比发现补丁直接阻断了后续CAutoImpersonate::ImpersonateUserHighestPrivsCWerComReport::_SubmitReport的调用

//未修复__int64 __fastcall CWerComReport::SubmitReport(        CWerComReport *this,        unsigned __int16 *a2,        unsigned int a3,        struct IWerReportSubmitCallback *a4,        unsigned __int16 **a5,        unsigned int *a6){  int v10; // ebx  int v12; // [rsp+30h] [rbp-18h] BYREF  __int64 v13; // [rsp+38h] [rbp-10h]  v13 = -2i64;  v12 = 2;  if ( !CAutoImpersonate::g_bEnableImpersonate    || (v10 = CAutoImpersonate::ImpersonateUserHighestPrivs((CAutoImpersonate *)&v12), v10 >= 0) )  {    v10 = CWerComReport::_SubmitReport((CWerComReport *)((char *)this - 24), a2, a3, a4, a5, a6);  }  CAutoImpersonate::~CAutoImpersonate((CAutoImpersonate *)&v12);  return (unsigned int)v10;}// 修复代码__int64 __fastcall CWerComReport::SubmitReport(        CWerComReport *this,        unsigned __int16 *a2,        unsigned int a3,        struct IWerReportSubmitCallback *a4,        unsigned __int16 **a5,        unsigned int *a6){  int v11; // ebx  int v12; // [rsp+30h] [rbp-18h] BYREF  __int64 v13; // [rsp+38h] [rbp-10h]  v13 = -2i64;  if ( (unsigned __int8)wil::details::FeatureImpl<__WilFeatureTraits_Feature_MSRC80633_DisableWerCplSupport>::__private_IsEnabled(&`wil::Feature<__WilFeatureTraits_Feature_MSRC80633_DisableWerCplSupport>::GetImpl'::`2'::impl) )    return 0x80004001i64;  v12 = 2;  if ( !CAutoImpersonate::g_bEnableImpersonate    || (v11 = CAutoImpersonate::ImpersonateUserHighestPrivs((CAutoImpersonate *)&v12), v11 >= 0) )  {    v11 = CWerComReport::_SubmitReport((CWerComReport *)((char *)this - 24), a2, a3, a4, a5, a6);  }  CAutoImpersonate::~CAutoImpersonate((CAutoImpersonate *)&v12);  return (unsigned int)v11;}

根据函数名CAutoImpersonate::ImpersonateUserHighestPrivs可知,该函数为模拟用户最高的权限并提交report

动态调试

开启Problem Reports Control Panel Support服务,对应路径为C:WindowsSystem32svchost.exe -k netsvcs -p。使用oleviewdotnet查询Problem Reports Control Panel Support服务对应的ole信息

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

对应的COM接口的CLSID为

  • CLSID: 0E9A7BB5-F699-4D66-8A47-B919F5B6A1DB

  • AppID: 136A0DC7-DF5C-4271-A2AC-15DF1A1323F2CVE-2023-36874 Windows 错误报告服务权限提升漏洞查看这个COM的接口信息

class __declspec(uuid("6620c14b-70ae-4d4e-a4f6-91a7dcc582c2")) IErcLuaSupport : public IUnknown {public:    virtual HRESULT __stdcall Proc3(/* Stack Offset: 8 */ IWerStoreFactory** p0);};class __declspec(uuid("4904c154-426f-4c88-8ec2-4543d18670f7")) IWerStoreFactory : public IUnknown {public:    virtual HRESULT __stdcall Proc3(/* Stack Offset: 8 */ IWerStore** p0);    virtual HRESULT __stdcall Proc4(/* Stack Offset: 8 */ IWerStore** p0);};class __declspec(uuid("1e3a0e4f-1412-444f-8a94-fc6a09cd4195")) IWerStore : public IUnknown {public:    virtual HRESULT __stdcall Proc3();    virtual HRESULT __stdcall Proc4(/* Stack Offset: 8 */ BSTR* p0);    virtual HRESULT __stdcall Proc5(/* Stack Offset: 8 */ BSTR p0);    virtual HRESULT __stdcall Proc6(/* Stack Offset: 8 */ BSTR p0, /* Stack Offset: 16 */ IWerReport** p1);    virtual HRESULT __stdcall Proc7(/* Stack Offset: 8 */ BSTR p0, /* Stack Offset: 16 */ BSTR* p1);};class __declspec(uuid("d01b8f28-0bd1-4652-a415-8229f5ee506c")) IWerReport : public IUnknown {public:    virtual HRESULT __stdcall Proc3(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc4(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc5(/* Stack Offset: 8 */ BSTR* p0);    virtual HRESULT __stdcall Proc6(/* Stack Offset: 8 */ IWerKeyValueList** p0);    virtual HRESULT __stdcall Proc7(/* Stack Offset: 8 */ IWerKeyValueList** p0);    virtual HRESULT __stdcall Proc8(/* Stack Offset: 8 */ IWerStringList** p0);    virtual HRESULT __stdcall Proc9(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc10(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc11(/* Stack Offset: 8 */ BSTR* p0);    virtual HRESULT __stdcall Proc12(/* Stack Offset: 8 */ BSTR* p0);    virtual HRESULT __stdcall Proc13(/* Stack Offset: 8 */ IWerStringList** p0);    virtual HRESULT __stdcall Proc14(/* Stack Offset: 8 */ IWerStringList** p0);    virtual HRESULT __stdcall Proc15(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc16(/* Stack Offset: 8 */ struct Struct_1* p0);    virtual HRESULT __stdcall Proc17(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc18(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc19(/* Stack Offset: 8 */ int64_t* p0);    virtual HRESULT __stdcall Proc20(/* Stack Offset: 8 */ BSTR p0, /* Stack Offset: 16 */ BSTR* p1);    virtual HRESULT __stdcall Proc21(/* Stack Offset: 8 */ BSTR* p0);    virtual HRESULT __stdcall Proc22(/* Stack Offset: 8 */ int64_t p0, /* Stack Offset: 16 */ int64_t* p1, /* Stack Offset: 24 */ int64_t* p2, /* Stack Offset: 32 */ BSTR* p3, /* Stack Offset: 40 */ BSTR* p4);    virtual HRESULT __stdcall Proc23(/* Stack Offset: 8 */ int64_t p0, /* Stack Offset: 16 */ BSTR* p1);    virtual HRESULT __stdcall Proc24(/* Stack Offset: 8 */ BSTR p0, /* Stack Offset: 16 */ int64_t p1, /* Stack Offset: 24 */ IWerReportSubmitCallback* p2, /* Stack Offset: 32 */ /* unique */BSTR* p3, /* Stack Offset: 40 */ /* unique */int64_t* p4);    virtual HRESULT __stdcall Proc25();};

这里需要知道Windows的COM模型,COM模型定义了二进制标准,以支持组件复用。将操作系统API抽象成了接口,可以通过接口的标识符实例化COM对象并通过COM对象调用服务接口。即

当使用COM接口调用error reporting 服务并提交错误报告时,error reporting会启动 C:WindowsSystem32wermgr.exe,并且启动时权限为 NT AUTHORITYSYSTEM

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

追溯调用栈查看此事件的调用栈,wer!WerpAuxmdMapFile+0x3887d 处调用了CreateProcessW

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

wer!WerpAuxmdMapFile+0x3887d位于 UtilLaunchWerManager函数内,代码如下

__int64 __fastcall UtilLaunchWerManager(        const unsigned __int16 **a1,        __int64 a2,        __int64 a3,        void *a4,        void **a5,        void **a6,        unsigned int a7,        void **a8){  ....  WCHAR Buffer[264]; // [rsp+148h] [rbp+40h] BYREF  v43 = -2i64;  v39 = a1;  v8 = a5;  lpValue = a8;  memset_0(Buffer, 0, 0x208ui64);  lpCommandLine[0] = 0i64;  lpCommandLine[1] = 0i64;  .....    goto LABEL_67;  }  v11 = StringCchCatW(Buffer, 0x104ui64, L"\wermgr.exe");  v12 = v11;  if ( v11 >= 0 )  {    v12 = CString::Sprintf((CString *)lpCommandLine, L""%s" ", Buffer);    if ( (v12 & 0x80000000) != 0 )    {      if ( WPP_GLOBAL_Control != (HKEY)&WPP_GLOBAL_Control && ((_BYTE)WPP_GLOBAL_Control[7] & 1) != 0 )      {        WPP_SF_S(*((_QWORD *)WPP_GLOBAL_Control + 2), 20i64, &WPP_80b9a2815f1633611b5141c011dbf465_Traceguids, Buffer);        goto LABEL_37;      }      goto LABEL_38;    }    v13 = 0;    v14 = lpCommandLine[0];    while ( v13 < 0xE )    {      .....        v19 = CString::Append((CString *)lpCommandLine, v40[0]);        if ( v19 >= 0 || WPP_GLOBAL_Control == (HKEY)&WPP_GLOBAL_Control || ((_BYTE)WPP_GLOBAL_Control[7] & 1) == 0 )        {          v14 = lpCommandLine[0];        }        ....    if ( UpdateProcThreadAttribute(v10, 0, 0x20002ui64, lpValue, 8i64 * a7, 0i64, 0i64) )    {      StartupInfo.cb = 112;      v45 = v10;      if ( CreateProcessW(Buffer, v14, 0i64, 0i64, 2, 0x80000u, 0i64, 0i64, &StartupInfo, &hObject) )      {        v12 = 0;      }      ......}
向上追溯调用栈,UtilLaunchWerManager函数由 CReportManager::ReportProblemOutOfProcess调用, 再上层函数为CReportManager::ReportProblem,CReportManager::ReportProblem由ReportHandleInstance::SubmitReport调用,在上层函数为WerpSubmitReportFromStore。在wecplsupport!DllCanUnloadNew+0x2bf2处调用了wer.dll!WerpSubmitReportFromStore函数。

wercplsupport!DllCanUnloadNew+0x2bf2实际位于 wercplsupport!CWerComReport::_SubmitReport函数内,代码如下。

__int64 __fastcall CWerComReport::_SubmitReport(        void **this,        unsigned __int16 *a2,        unsigned int a3,        struct IUnknown *a4,        unsigned __int16 **a5,        unsigned int *a6){  ......  v24 = &CStubUI::`vftable';  if ( a4 )    ((void (__fastcall *)(struct IUnknown *))a4->lpVtbl->AddRef)(a4);  v25 = a4;  v23[0] = 0i64;  TokenHandle = 0i64;  v26 = 0;  v10 = a5;  if ( a5 )  {    SysFreeString(*a5);    *v10 = 0i64;  }  WerApiLock = CWerApiAutoLock::TryGetWerApiLock((CWerApiAutoLock *)v23, (struct CWerComReport *)this);  if ( WerApiLock >= 0 )  {.....        }        else        {          CurrentThread = GetCurrentThread();          if ( OpenThreadToken(CurrentThread, 0xF01FFu, 1, &TokenHandle) || GetLastError() == 1008 )          {            .....            }            else            {              WerApiLock = WerpSubmitReportFromStore(                             *((void **)this[5] + 4),                             a2,                             this[4],                             (struct IReportUI *)((unsigned __int64)&v24 & -(__int64)(a4 != 0i64)),                             &v21,                             a3,                             (enum _WER_SUBMIT_RESULT *)&v20);.....}

_SubmitReport由 CWerComReport::SubmitReport调用,而 

CWerComReport::SubmitReport为IWerReport接口公开的函数。

__int64 __fastcall CWerComReport::SubmitReport(        CWerComReport *this,        unsigned __int16 *a2,        unsigned int a3,        struct IWerReportSubmitCallback *a4,        unsigned __int16 **a5,        unsigned int *a6){  int v10; // ebx  int v12; // [rsp+30h] [rbp-18h] BYREF  __int64 v13; // [rsp+38h] [rbp-10h]  v13 = -2i64;  v12 = 2;  if ( !CAutoImpersonate::g_bEnableImpersonate    || (v10 = CAutoImpersonate::ImpersonateUserHighestPrivs((CAutoImpersonate *)&v12), v10 >= 0) )  {    v10 = CWerComReport::_SubmitReport((CWerComReport *)((char *)this - 24), a2, a3, a4, a5, a6);  }  CAutoImpersonate::~CAutoImpersonate((CAutoImpersonate *)&v12);  return (unsigned int)v10;}
所以可以总结出调用链:wecplsupport!CWerComReport::SubmitReport->

wecplsupport!CWerComReport::_SubmitReport->wer.dll!WerpSubmitReportFromStore...->CreateProcessW

问题在于在调用CreateProcessW时,CreateProcessW会使用攻击者设置的文件重定向,但将使用调用CreateProcessW的进程的security token设置进程的context,而不是模拟token来设置进程的security context。

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

CVE-2023-36874 Windows 错误报告服务权限提升漏洞

也就是攻击者可以通过文件重定向将 C:WindowsSystem32重定向到攻击者可控目录,并且在可控目录写入恶意 wermgr.exe,当触发CreateProcessW时,CreateProcessW将使用攻击者控制的目录的wermgr.exe文件而不是系统在C:WindowsSystem32目录下的wermgr.exe文件。并且该进程上下文继承了调用进程的上下文,即继承了wer服务的权限。

动态调试

UtilLaunchWerManager断点

bp wer!UtilLaunchWerManager

调试器断下

0:006> gBreakpoint 2 hitwer!UtilLaunchWerManager+0xf3:00007ffb`7b11a23f e87cb3f7ff      call    wer!StringCchCatW (00007ffb`7b0955c0)0:006> rrcxrcx=00000041e2efbce0

补丁分析

前面知道补丁直接阻断了后续调用_submit,也就没办法再调用CreateProcess,从而阻断了调用链。

PoC:

https://github.com/Wh04m1001/CVE-2023-36874

需要注意的是运行poc需要使用不在admin组的用户,新增用户运行

net user test 123456 /add

参考链接

https://www.crowdstrike.com/blog/falcon-complete-zero-day-exploit-cve-2023-36874/

原文始发于微信公众号(闲聊趣说):CVE-2023-36874 Windows 错误报告服务权限提升漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月15日21:00:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2023-36874 Windows 错误报告服务权限提升漏洞https://cn-sec.com/archives/2499581.html

发表评论

匿名网友 填写信息