None
An out-of-bounds read vulnerability exists in the License Update Field Type 0xD3 functionality of Microsoft Windows CLIPSP.SYS 10.0.22621 Build 22621, 10.0.26080.1 and 10.0.26085.1. A specially crafted license blob can lead to denial of service. An attacker can use the NtQuerySystemInformation function call to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Microsoft CLIPSP.SYS 10.0.22621 Build 22621
Microsoft CLIPSP.SYS 10.0.26080.1
Microsoft CLIPSP.SYS 10.0.26085.1
Microsoft Windows 11 Pro 23H2 22631.3296
Microsoft Windows 11 Pro 24H2 Insider Preview 26085.1
CLIPSP.SYS - https://www.microsoft.com/en-us/windows/windows-11 Windows - https://www.microsoft.com/en-us/windows/
6.8 - CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H
CWE-125 - Out-of-bounds Read
CLIPSP.SYS is a driver used to implement Client License System Policy on Windows 10 and 11. It provides the functions used when handling most of the requests involving licensing, notably the implementation of many use cases involved with the SystemPolicyInformation class used in conjunction with NtQuerySystemInformation.
When calling NtQuerySystemInformation
with the SystemPolicyInformation
class, ntoskrnl
will call ExHandleSPCall2
that will process the data provided. The format is mostly undocumented and encrypted using Microsoft’s Warbird. Upon decryption of the data provided, a call handler is invoked based on the command_id
provided and dispatches the payload to the relevant function (e.g. SPCallServerHandleClepKdf
, SPCallServerHandleUpdateLicense
, etc.). A substential amount of these functions are wrapers around clipsp
functions that are stored as function pointers in the nt!g_kernelCallbacks
globlal array.
The SPCallServerHandleUpdateLicense
(command_id
:100) will accept a License blob whose format is also undocumented. Once installed, these license files are stored in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\{7746D80F-97E0-4E26-9543-26B41FC22F79}\{A25AE4F2-1B96-4CED-8007-AA30E9B1A218}
key, only accessible to the SYSTEM user.
The format of this license file is TLV (Tag-length-value) following this format:
struct __unaligned __declspec(align(1)) LicenseParsing_entry
{
__int16 type;
__int16 reserved;
int entry_size;
char value[ANYSIZE_ARRAY]; //expected to be of size entry_size
};
The code snippets below are decompiled output and variables names were assumed from context or retrieved from public symbol servers, sdk, etc.
The addresses provided are for the canary build 26085.1.amd64fre.ge_release.240315-1352
There exists multiple out-of-bound reads vulnerabilities when handling various license field types. This vulnerability can be triggered by feeding to the SPCallServerHandleUpdateLicense
function a license filed that has been tampered with.
When calling SPCallServerHandleUpdateLicense
the data will eventually be past to an obfuscated function inside clipsp
and stored in an array (see 0x0001C00E8BA3):
License->field_0[v13].entry_size = v10->entry_size;
License->field_0[v13].entry_field2 = v10->field_2;
License->field_0[v13].entry_ptr = (__int64)&v10->first_byte;
Where v13
is the internal type associated with an entry type in the license file.
In most of the case below, the root cause of the problem is reading data in entry_ptr
without verifying first that entry_size
accomodates for the extent of the data read (e.g. read 2 bytes of data at offset 8 without verifying that entry_size >= 8+2
)
When installing a new license containing keyholder information, an out-of-bound read can occur if a truncated blob of type 0xD3
(internal type 2
) is appended at the end of the license such as {0xD3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xAA }
.
The following function gets invoked when handling keyholder information while/after installing a new license:
//001C00E77D8
__int64 __fastcall __spoils<rax,rdx> LicenseStruct_get_dref0_for_type2(LicenseStruct *License)
{
unsigned int *entry_ptr; // rdx
__int64 result; // rax
entry_ptr = (unsigned int *)License->field_0[2].entry_ptr;
result = 0i64;
if ( entry_ptr )
return *entry_ptr; //out of bound read happens here
return result;
The function above is not necessarily invoked upon installation of the license but when key data is accessed (e.g. tampering with an existing application license and then open/close the application)
2024-04-12 - Vendor Disclosure
2024-07-09 - Vendor Patch Release
2024-08-13 - Public Release
Discovered by Philippe Laulheret of Cisco Talos.