CVE-2024-38148 — Windows Secure Channel (schannel) CTlsMessageFragment Use-After-Free

Last updated: 2026-07-02
Severity: High — Microsoft rated DoS; write-up argues UAF with RCE potential
Component: schannel (Secure Channel — Windows SSL/TLS) — CSsl3TlsContext
Bug Class: Use-After-Free (dangling back-reference into a freed TLS context)
Patch: feature-flag gate that disables the offending pointer assignment
Related: Use After Free, CVE-2025-21297 (RD Gateway UAF), CVE-2024-29050 (CryptoAPI)

Vulnerability Summary

A use-after-free in Windows Secure Channel (schannel), Microsoft’s SSL/TLS implementation. Microsoft’s advisory characterises the issue as denial-of-service, but the write-up shows it is a genuine UAF: during TLS context construction a pointer to a message-fragment object is copied so that the fragment keeps a back-reference to a context structure that is later freed. Dereferencing that stale reference during connection cleanup yields a dangling virtual-table pointer — the basis for potential unauthenticated remote code execution.


Affected Code Path

CSsl3TlsServerContext::ProcessRecord()          // allocates M1 (CTlsMessageFragment)
  → CTlsMessageFragment::Initialize()           // M1[0] holds a back-ref to context a2
  → CSsl3TlsContext::CSsl3TlsContext(this, a2)   // *(this+0x1D8) = *(a2+0x1D8)  → copies M1 pointer
  ...
  → CTls13ServerContext::CleanupConnectedState() // dereferences the stale reference → UAF

Root Cause Analysis

In the CSsl3TlsContext::CSsl3TlsContext constructor a pointer is copied from parameter a2 into offset 0x1D8 (472) of the new context:

*(QWORD*)(this + 472) = *(QWORD*)(a2 + 472);

That pointer references a freshly-allocated block M1, a CTlsMessageFragment. Critically, M1’s first 8-byte field holds a reference back to the original a2 context, and this back-reference is not updated when the pointer is copied. When a2 is torn down during cleanup, M1 still points at the freed a2; later code (CTls13ServerContext::CleanupConnectedState) walks that back-reference and dereferences freed memory. Because the freed object is a C++ object reached via virtual dispatch, this is a controllable UAF rather than a null-deref.


Patch Analysis

The patch wraps the offending assignment in a WIL feature check and, when the feature is enabled, both skips the copy and clears the source:

if (!FeatureImpl<...>::__private_IsEnabled(...)) {
    *(QWORD*)(this + 472) = *(QWORD*)(a2 + 472);
    *(QWORD*)(a2 + 472)  = 0i64;
}

Net effect: M1’s first field no longer references a context that may be freed prematurely, so the dangling back-reference cannot form.


Component Functions

FunctionRole
CSsl3TlsServerContext::ProcessRecordallocates M1 (CTlsMessageFragment)
CTlsMessageFragment::Initializecreates the dangling back-reference
CSsl3TlsContext::CSsl3TlsContextvulnerable pointer copy (offset 0x1D8)
CTls13ServerContext::CleanupConnectedStatetriggers the UAF

References