Security mitigation for the Common Log Filesystem (CLFS)
Microsoft will soon be releasing a new security mitigation for the Common Log File System (CLFS) to the Windows Insiders Canary channel. In the past five years, 24 CVEs impacting CLFS have been identified and mitigated, making it one of the largest targets for vulnerability research in Windows. Rather than continuing to address single issues as they are discovered, the Microsoft Offensive Research & Security Engineering (MORSE) team has worked to add a new verification step to parsing CLFS logfiles, which aims to address a class of vulnerabilities all at once. This work will help protect our customers across the Windows ecosystem before they are impacted by potential security issues.
CLFS Overview
CLFS is a general-purpose logging service that can be used by software clients running in user-mode or kernel-mode. This service provides the transaction functionality for the Kernel Transaction Manager of the Windows kernel, which Transactional Registry (TxR) and Transactional NTFS (TxF) are built upon. While used in multiple places in the Windows kernel, a public user-mode API is also offered and can be utilized for any application wanting to store log records on the file system.
CLFS stores all log information and log records in a set of files, referred to as a “logfile”, which persists at a user-defined location on the file system. While the logfile is comprised of multiple files, the CLFS driver manages them as a single unit by creating a file handle for the whole set. The logfile is made up of one “Base Log File” (BLF), which holds the necessary metadata for the log, and two or more “container files”, which is where user-supplied log records are stored.
The custom file format used for the logfile is mostly undocumented, however, some high level information about the internal structures can be found at CLFS Stable Storage. Like many binary file formats, the internal data structures are read into memory, mapped to C/C++ structures, and later operated against by application code. For both the CLFS user-mode and kernel-mode API, it is the responsibility of the driver to read, parse, and ensure the validity of the data structures that make up this custom file format.
Attack Surface
It has proven to be a difficult task to validate all data read from the logfile due to the complexity of the data structures and how they are used. Out of the 24 CVE’s reported in the past 5 years, 19 have involved exploiting a logic bug in the CLFS driver caused by improper validation of one of its data structures. Included in these 19 CVEs are vulnerabilities with known exploits, such as CVE-2022-37969, CVE-2023-23376, and CVE-2023-28252. To trigger such a bug, an attacker can utilize the file system API (e.g. CreateFileW and WriteFile) to either craft a new malicious logfile or corrupt an existing logfile.
Mitigation Overview
Instead of trying to validate individual values in logfile data structures, this security mitigation provides CLFS the ability to detect when logfiles have been modified by anything other than the CLFS driver itself. This has been accomplished by adding Hash-based Message Authentication Codes (HMAC) to the end of the logfile. An HMAC is a special kind of hash that is produced by hashing input data (in this case, logfile data) with a secret cryptographic key. Because the secret key is part of the hashing algorithm, calculating the HMAC for the same file data with different cryptographic keys will result in different hashes.
Just as you would validate the integrity of a file you downloaded from the internet by checking its hash or checksum, CLFS can validate the integrity of its logfiles by calculating its HMAC and comparing it to the HMAC stored inside the logfile. As long as the cryptographic key is unknown to the attacker, they will not have the information needed to produce a valid HMAC that CLFS will accept. Currently, only CLFS (SYSTEM) and Administrators have access to this cryptographic key.
Anytime CLFS wants to make a modification to a logfile, such as adding a new log record to a container file or updating its metadata in the BLF, a new HMAC will need to be calculated using the contents of the entire file. Modifications to logfiles occur frequently, so it would be infeasible for CLFS to be repeatedly reading the file for HMAC calculation anytime a modification occurs, especially since CLFS container files can be upwards to 4GB in size. To reduce the overhead required for maintaining a HMAC, CLFS utilizes a Merkle tree (also known as a hash tree), which drastically lowers the amount of file reading needed to be done whenever a new HMAC needs to be calculated. While the Merkle tree makes HMAC maintenance feasible, it requires additional data to be stored on the file system. Refer to the “User Impact” section of this article for estimates on the storage overhead introduced by this mitigation.
Mitigation Adoption Period / Learning mode
A system receiving an update with this version of CLFS will likely have existing logfiles on the system that do not have authentication codes. To ensure these logfiles get transitioned over to the new format, the system will place the CLFS driver in a “learning mode”, which will instruct CLFS to automatically add HMACs to logfiles that do not have them. The automatic addition of authentication codes will occur at logfile open and only if the calling thread has write access to the underlying files. Currently, the adoption period lasts for 90 days, starting from the time in which the system first booted with this version of CLFS. After this 90-day adoption period has lapsed, the driver will automatically transition into enforcement mode on its next boot, after which CLFS will expect all logfiles to contain valid HMAC. Note that this 90-day value may change in the future.
For new installs of Windows, CLFS will start in enforcement mode, as we do not expect there to be any existing logfiles that need to be transitioned over to the new format.
FSUTIL Command
The fsutil clfs authenticate command line utility can be used by Administrators to add or correct authentication codes for an existing logfile. This command will be useful for the following scenarios:
If a logfile is not opened during the mitigation adoption period, and therefore was not automatically transitioned over to the new format, this command can be used to add authentication codes to the logfile.
Since the authentication codes are created using a system-unique cryptographic key using the local system’s cryptographic key, allowing you to open the logfile that was created on another system.
Usage:
PS D:> fsutil.exe clfs authenticate
Usage: fsutil clfs authenticate <Logfile BLF path>
Eg: fsutil clfs authenticate “C:example_log.blf”
Add authentication support to a CLFS logfile that has invalid or
missing authentication codes. Authentication codes will be written
to the Base Logfile (.blf) and all containers associated with the logfile.
It is required that this command be executed with administrative
privileges.
Configuration
Settings for this mitigation can be configured in a couple of ways. No matter what approach you take, you’ll need to be an Administrator.
1. Registry settings
Settings for this mitigation are stored in the registry under the key HKLMSYSTEMCurrentControlSetServicesCLFSAuthentication. There are two registry values that can be viewed and modified by administrators:
Mode: The operating mode of the mitigation
0: The mitigation is enforced. CLFS will fail to open logfiles that have missing or invalid authentication codes. After 90 days of running the system with this version of the driver, CLFS will automatically transition into enforcement mode.
1: The mitigation is in learning mode. CLFS will always open logfiles. If a logfile is missing authentication codes, then CLFS will generate and write the codes to the file (assuming caller has write access).
2: The mitigation was disabled by an Administrator.
EnforcementTransitionPeriod: The amount of time, in seconds, that the system will spend in the adoption period. If this value is zero, then the system will not automatically transition into enforcement.
To disable the mitigation, an Administrator can run the following powershell command:
Set-ItemProperty -Path “HKLM:SYSTEMCurrentControlSetServicesCLFSAuthentication” -Name Mode -Value 2
To prolong the mitigation’s adoption period, an Administrator can run the following powershell command:
Set-ItemProperty -Path “HKLM:SYSTEMCurrentControlSetServicesCLFSAuthentication” -Name EnforcementTransitionPeriod -Value 2592000
2. Group Policy
The mitigation can be controlled using the ClfsAuthenticationChecking Group Policy setting (“Enable / disable CLFS logfile authentication”). This policy setting can be found under “Administrative TemplatesSystemFilesystem” in gpedit.exe.
Like all group policy settings, the CLFS logfile authentication setting can be in one of three states:
“Not Configured” (Default) – The mitigation is allowed to be enabled. CLFS will check its local registry mode (HKLMSYSTEMCurrentControlSetServicesCLFSAuthentication [Mode]).
“Enabled” – The same as “Not Configured”. The mitigation is allowed to be enabled but CLFS will first check local registry settings.
“Disabled” – The mitigation is disabled. CLFS will not check for authentication codes and will attempt to open logfiles that may be corrupted.
Note that if the mitigation goes from a disabled to enabled state (via Group Policy), then the mitigation adoption period will automatically be repeated since there will likely be logfiles on the system that were created without authentication codes during the time the mitigation was disabled.
User Impact
This mitigation may impact consumers of the CLFS API in the following ways:
Because the cryptographic key used to make the authentication codes is system-unique, logfiles are no longer portable between systems. To open a logfile that was created on another system, an Administrator must first use the fsutil clfs authenticate utility to authenticate the logfile using the local system’s cryptographic key.
A new file, with the extension “.cnpf”, will be stored alongside the BLF and data containers. If the BLF for a logfile is located at “C:UsersUserexample.blf”, its “patch file” should be located at “C:UsersUserexample.blf.cnpf”. If a logfile is not cleanly closed, the patch file will hold data needed for CLFS to recover the logfile. The patch file will be created with the same security attributes as the file it provides recovery information for. This file will be around the same size as “FlushThreshold” (HKLMSYSTEMCurrentControlSetServicesCLFSParameters [FlushThreshold]).
Additional file space is required to store authentication codes. The amount of space needed for authentication codes depends on the size of the file. Refer to the list below for an estimate on how much additional data will be required for your logfiles:
512KB container files require an additional ~8192 bytes.
1024KB container files require an additional ~12288 bytes.
10MB container files require an additional ~90112 bytes.
100MB container files require an additional ~57344 bytes.
4GB container files require an additional ~2101248 bytes.
Due to the increase in I/O operations for maintaining authentication codes, the time it takes to create, open, and write records to logfiles has increased. The increase in time for logfile creation and logfile open depends entirely on the size of the containers, with larger logfiles having a much more noticeable impact. On average, the amount of time it takes to write to a record to a logfile has doubled.
Changes to CLFS API
To avoid breaking changes to the CLFS API, existing error codes are used to report integrity check failures to the caller:
If CreateLogFile fails, then GetLastError will return the ERROR_LOG_METADATA_CORRUPT error code when CLFS fails to verify the integrity of the logfile.
For ClfsCreateLogFile, the STATUS_LOG_METADATA_CORRUPT status is returned when CLFS fails to verify the integrity of the logfile.
Microsoft Tech Community – Latest Blogs –Read More