CVE-2025-60709 - Windows Common Log File System Driver Elevation of Privilege Vulnerability

Ghostbyt3 Ghostbyt3
Table of Contents

A vulnerability in the Windows Common Log File System (CLFS) driver allows out-of-bounds memory reads due to insufficient bounds checking in ClfsGetFirstRecord(). The function validates that attacker-controlled record offsets don’t exceed buffer_size + 40 instead of buffer_size, enabling reads of up to 40 bytes beyond allocated buffers, potentially leaking sensitive kernel memory for information disclosure or exploit chain development.

CVE-2025-60709: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-60709
Vulnerability Type: Out-of-bounds Read
Driver Version: clfs.sys - 10.0.26100.7019

Vulnerability analysis

From the patch diffing results, it was found that the ClfsGetFirstRecord() function has significant changes, whereas the other functions have only minor changes.

image.png

The vulnerable function is ClfsGetFirstRecord(), and as the name suggests, it retrieves the first record of a CLFS log block. Here, a1 points to a CLFS_LOG_BLOCK_HEADER structure, and a2 is the buffer size.

  • Line 8 – It loads the value at a1 + 0x28, which corresponds to the first entry of the RecordOffsets array, into v2. Therefore, v2 = RecordOffsets[0] and represents the offset of the first record.
  • Line 11 – It obtains the pointer to the first record by computing a1 + v2 (a1[v2]). This value is stored in result, which the function will return.
  • The problem lies in the bounds validation.
  • Line 9 – It checks that the first offset (RecordOffsets[0]) does not exceed 0xFFFFFFD8, which is just a large sanity limit.
  • Line 12 – This is where the actual issue appears. Instead of properly checking that the offset stays within the buffer, the function only fails when RecordOffsets[0] > buffer_size + 40.
  • As a result, the function incorrectly accepts offsets in the range from buffer_size (a2) up to buffer_size + 0x28 (40 bytes). Any value in this range produces an out‑of‑bounds pointer, leading to an out‑of‑bounds read.

image.png

typedef struct _CLFS_LOG_BLOCK_HEADER
{
    UCHAR MajorVersion;
    UCHAR MinorVersion;
    UCHAR Usn;
    CLFS_CLIENT_ID ClientId;
    USHORT TotalSectorCount;
    USHORT ValidSectorCount;
    ULONG Padding;
    ULONG Checksum;
    ULONG Flags;
    CLFS_LSN CurrentLsn;
    CLFS_LSN NextLsn;
    ULONG RecordOffsets[16];
    ULONG SignaturesOffset;
} CLFS_LOG_BLOCK_HEADER, *PCLFS_LOG_BLOCK_HEADER;

In order to exploit this vulnerability, the Base Log File must set RecordOffsets[0] to an offset that is larger than the buffer size but not larger than buffer_size + 0x28. To reach this vulnerable function, the shortest path is via CClfsLogFcbPhysical::AppendRegion() function.

image.png

Patch Analysis

In the patched version, the function first loads RecordOffsets[0] into v4. It then computes v5 = v4 + 40 (i.e., RecordOffsets[0] + 0x28). In the new bounds check (line 17), it ensures that RecordOffsets[0] + 40 does not exceed the buffer size (a2/v2 + 40). This patch fixes the original bug by ensuring that RecordOffsets[0] + 0x28 must not exceed the buffer size, preventing the out‑of‑bounds read.

image.png