POC详情: d4ea9d4ec59a70610a7a1cd4457ad1bea1cae6dd

来源
关联漏洞
标题: Microsoft Windows Common Log File System Driver 安全漏洞 (CVE-2023-36424)
描述:Microsoft Windows Common Log File System Driver是美国微软(Microsoft)公司的通用日志文件系统 (CLFS) API 提供了一个高性能、通用的日志文件子系统,专用客户端应用程序可以使用该子系统并且多个客户端可以共享以优化日志访问。 Microsoft Windows Common Log File System Driver存在安全漏洞。攻击者利用该漏洞可以提升权限。以下产品和版本受到影响:Windows 11 Version 23H2 for ARM
描述
Windows Kernel Pool (clfs.sys) Corruption Privilege Escalation
介绍
# Information
==============

Windows Kernel Pool (clfs.sys) Corruption Privilege Escalation. (CVE-2023-36424)

This repo contains technical analysis & working exploit.

Author: Nassim Asrir (@p1k4l4) || https://www.linkedin.com/in/nassim-asrir-b73a57122/

# Vulnerability
================

There is a pool overflow in clfs.sys mini filter driver. Information on this can be read on:

1 - https://googleprojectzero.blogspot.com/2021/01/hunting-for-bugs-in-windows-mini-filter.html

2 - https://www.zerodayinitiative.com/blog/2021/7/19/cve-2021-31969-underflowing-in-the-clouds

The reason is that the driver is not sufficiently checks a data that comes from NTFS reparse point.

We will consider clfs.sys version 10.0.22621.2134 (Windows 11 22H2 22621.2215)

The function HsmFltProcessHSMControl is responsible for processing cloud filter FSCTLs. For an operation with code 0xC0000003 , it will eventually call HsmFltProcessUpdatePlaceholder . 

After some processing the execution flow will reach HsmiOpUpdatePlaceholderDirectory and then finally HsmpRpCommitNoLock: 

```c
__int64 __fastcall HsmpRpCommitNoLock(__int64 a1, __int64 a2, struct _FILE_OBJECT *a3, char a4, char a5)

{ .....

v26 = FileObject; LODWORD(v9) = HsmpRpReadBuffer(*(PFLT_INSTANCE *)(v164 + 32), FileObject, (unsigned __int16 **)&P); // [1*]

HsmDbgBreakOnStatus((unsigned int)v9);

if ( (_DWORD)v9 == -1073741195 ) .....

goto LABEL_55; }

if ( (v9 & 0x80000000) != 0i64 )

goto LABEL_9;}
 

if ( (*(_DWORD *)P & 0xFFFF0FFF) != dword_1C0027650 )// Is
Cloud Reparse Tag?
{
LODWORD(v9) = 0xC000CF0B;
.....
goto LABEL_54;
}
v32 = *((unsigned __int16 *)P + 2);
v9 = (unsigned int)HsmpRpValidateBuffer((__int64)P + 8, v32); [2*]
.....
Pool2 = ExAllocatePool2(0x100i64, 0x4000i64, 'pRsH'); // [3*]
v146 = (_DWORD *)Pool2;
v13 = (void *)Pool2;
if ( Pool2 )
{
v64 = v159_10;
v65 = Pool2 + 4;
if ( v8 && *((_WORD *)v8 + 7) > 0xAu )
v64 = *((_WORD *)v8 + 7);
v9 = Pool2 + 20;
v66 = (unsigned int *)(Pool2 + 12);
*(_OWORD *)v65 = 0i64;
*(_WORD *)(Pool2 + 16) = 0;
*(_WORD *)(Pool2 + 18) = v64;
*(_DWORD *)(Pool2 + 12) = 8 * v64 + 16;
*(_DWORD *)v65 = 'pReF';
memset((void *)(Pool2 + 20), 0, 8i64 * v64);
.....
if ( v8 )
{
v127 = 10;
if ( *((_WORD *)v8 + 7) > 0xAu ) // [4*]
{
if ( WPP_GLOBAL_Control !=
(PDEVICE_OBJECT)&WPP_GLOBAL_Control
&& (HIDWORD(WPP_GLOBAL_Control->Timer) & 1) != 0

&& BYTE1(WPP_GLOBAL_Control->Timer) >= 4u )
{
WPP_SF_qiq(WPP_GLOBAL_Control->AttachedDevice, v86,
v87, a2, *(_QWORD *)(v156 + 32), FileObject);
}
while ( v127 < *((_WORD *)v8 + 7) )
{
*(_QWORD *)(v65 + 8i64 * v127 + 16) = *(_QWORD
*)&v8[8 * v127 + 16];
memmove(
(void *)(v65 + *v66),
&v8[*(unsigned int *)&v8[8 * v127 + 20]],
*(unsigned __int16 *)&v8[8 * v127 + 18]); //
[5*]
*(_DWORD *)(v65 + 8i64 * v127 + 20) = *v66;
*v66 += *(unsigned __int16 *)(v65 + 8i64 * v127++ +
18);
}
}
}
.....
}
```

`HsmpRpReadBuffer` [1*] retrieves reparse point data. This data contains WORD-size value *((_WORD *)v8 + 7) , specifying a count of the structured items. Each item has a Type field, Size and Offset to data fields. 

Which item type in which place is strictly predetermined. But only for the first 10 ones. For example, the type field of the first item must have a value equal to 0x7.

The driver will execute HsmpRpValidateBuffer [2*] to verify acquired data. Then [3*] will be allocated paged pool with fixed 0x4000 bytes size. And if reparsed point data has a Count value more than 10, then the

data of the items after the tenth will be copied into this fixed-size pool [4*] without any additional checks.

The validation inside HsmpRpValidateBuffer is insufficiant, because it checks only first 10 records. 

```c
__int64 __fastcall HsmpRpValidateBuffer(__int64 pBuf, unsigned int a2)
{
.....
v2 = a2 - 4;
pBuf2 = pBuf + 4;
LOBYTE(v5) = 0;
v6 = 0i64;
if ( a2 <= 4 )
v2 = 0;
v7 = 0;
v8 = *(_DWORD *)pBuf & 0xF;
if ( !v8 )
{
.....
return IsReparseBufferSupported;
}
if ( v8 > 1 )
{
....
}
v9 = 0;
v66 = 0;
if ( v2 < 0x18 )
goto ERROR_EXIT;
v9 = 1;
if ( *(_DWORD *)pBuf2 != 'pReF' )
goto ERROR_EXIT;
v9 = 2;
v10 = (unsigned int *)(pBuf + 0xC);
if ( (*(_BYTE *)(pBuf + 16) & 2) != 0 && *(_DWORD *)(pBuf +
8) != RtlComputeCrc32(0, (PUCHAR)(pBuf + 0xC), v2 - 8) )
goto ERROR_EXIT;
v11 = *v10;
v9 = 3;
if ( v2 < (unsigned int)v11 )
goto ERROR_EXIT;
v12 = *(unsigned __int16 *)(pBuf2 + 0xE);
v9 = 4;
if ( !(_WORD)v12 )
goto ERROR_EXIT;
v13 = 8 * v12 + 16;

v9 = 5;
if ( v13 >= v11 )
goto ERROR_EXIT;
v9 = 0x10000;
for ( i = 0; ; ++i )
{
v15 = *(unsigned __int16 *)(pBuf2 + 0xE);
if ( (unsigned int)v12 >= 0xA ) // [1*]
v15 = 10;
if ( i >= v15 )
break;
}
```

As we can see [1*] the code will verify only the first 10 items and ignores the case when there are more records.

# Exploitation
=================

The size of the vulnerable pool is 0x4000. The size is a multiple of page and therefore the segment allocation will be used [3].

For exploitation was used the technique described here[4]. Calling NtAlpcCreateResourceReserve will create a lot of handles and ovewriting one of them with the pointer to constructed fake _KALPC_RESERVE object will give us the ability to write to arbitrary kernel address.

To prepare the memory, we sequentially allocating pools of 0x4000 size, using pipes[5]. Then we will free every second pool, provide a place for vulnerable buffer. 

![Alt text](analysis1.png)

To read an arbitrary kernel address, the exploit utilised pipes. For this purpose we will overwrite AttributeValue pointer of the PipeAttribute structure. 

![Alt text](analysis2.png)

And afterwards, we can steal system token to overwrite token in the target process. 

Thanks for reading.
 

文件快照

[4.0K] /data/pocs/d4ea9d4ec59a70610a7a1cd4457ad1bea1cae6dd ├── [ 78K] analysis1.png ├── [ 51K] analysis2.png ├── [4.0K] CVE-2023-36424-exploit │   ├── [ 29K] polpol.cpp │   ├── [ 979] polpol.filters │   ├── [1.4K] polpol.sln │   ├── [ 168] polpol.user │   ├── [7.1K] polpol.vcxproj │   └── [ 168] polpol.vcxproj.user └── [5.5K] README.md 1 directory, 9 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。