# CVE-2026-50694 — Windows SSTP `sstpsvc.dll` Lockless Handle Lookup → Use-After-Free

---

## Summary

| | |
|---|---|
| **Product** | Windows — `sstpsvc.dll` (Secure Socket Tunneling Protocol service) |
| **CVE ID** | CVE-2026-50694 |
| **Impact** | Remote Code Execution |
| **MSRC severity** | **Critical** |
| **CVSS** | 8.1 / 7.1 — `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-416: Use After Free (unsynchronized handle lookup vs removal) |
| **Delivery** | Network, unauthenticated (`AV:N`, `PR:N`); `AC:H` — race between handle lookup and removal |
| **KB / Fixed build** | KB5101650 — `sstpsvc.dll` 10.0.26100.8875 (Win11 24H2 x64) |
| **Patch Date** | July 14, 2026 (2026-Jul) |
| **Pre-patch binary** | `sstpsvc.dll` 10.0.26100.8737 — SHA256 `729367a7ab204b1025d418245219defb65e0f436b76685e1569c170f4b9a1f39` |
| **Post-patch binary** | `sstpsvc.dll` 10.0.26100.8875 — SHA256 `416df55724c91f99087aa58f8dae317cc9851e8ebf7380ae0ccd9854567321d1` |
| **Feature flag** | `Feature_1207409977` — **the fix is CFR-gated** |
| **Exploitability** | Exploitation Less Likely; not publicly disclosed; not exploited (per MSRC) |

---

## Product Description

`sstpsvc.dll` is the Windows **SSTP** (Secure Socket Tunneling Protocol) VPN
service. It resolves client-supplied 32-bit handles to the corresponding
connection object via a handle table (`SstpSvcGlobals` handle table at index 22),
and each object is reference-counted for lifetime management.

---

## Vulnerability Summary

Pre-patch, the service looked up the object from a client handle **without holding
the handle-table lock**, and only afterward entered the object's *own* critical
section:

```c
// sstpsvc.dll (10.0.26100.8737) — PRE-PATCH, from our diff
if ( HfGetPointerFromHandle32(*((_QWORD*)SstpSvcGlobals + 22), handle, &obj) )   // *** no table lock ***
    ...
EnterCriticalSection((LPCRITICAL_SECTION)(obj + 288));                           // object lock, after the fact
```

Because the lookup — and the object's lifetime **reference acquisition** — were not
serialized against a **concurrent handle removal** (which takes the same table
lock), another thread could remove the handle and drop the last reference,
**freeing the object**, in the window between the lockless lookup and the code that
uses it. The service then operates on freed memory — a **use-after-free** (CWE-416).
Because SSTP processes network connections pre-authentication and runs privileged,
this is a Critical RCE.

---

## Prerequisites and Constraints

- Network, unauthenticated (`AV:N`, `PR:N`); `AC:H` reflects the race window.
- Race: drive a handle lookup concurrently with removal of the same handle so the
  object is freed between the lockless lookup and its use.
- Success yields a UAF in the SSTP service → RCE.

---

## Vulnerability Details

### Root Cause

The handle→object lookup and the lifetime reference were performed outside the
handle-table lock, so they were not atomic with respect to concurrent handle
removal / final dereference, allowing the object to be freed mid-use.

### The patch (confirmed — diff, .8737 → .8875)

Gated behind `Feature_1207409977`, the lookup **and the reference acquisition** are
moved **inside the handle-table critical section** (`SstpSvcGlobals + 0xB8`, i.e.
+184), so they are synchronized with any concurrent handle removal that requires
the same lock:

```c
// sstpsvc.dll (10.0.26100.8875) — PATCHED, feature-enabled branch (from our diff)
if ( Feature_1207409977__private_IsEnabledDeviceUsage() ) {
    EnterCriticalSection((LPCRITICAL_SECTION)(SstpSvcGlobals + 0xB8));   // *** table lock ***
    p = HfGetPointerFromHandle32(*((_QWORD*)SstpSvcGlobals + 22), handle, &obj);
    if ( p )
        *(int*)(obj + 0xD0) = *(int*)(obj + 0xD0) + 1;                   // *** AddRef under the lock ***
    LeaveCriticalSection((LPCRITICAL_SECTION)(SstpSvcGlobals + 0xB8));
}
else { /* legacy lockless lookup */ }
```

With the reference taken **while the table lock is held**, a concurrent removal
cannot free the object between lookup and use — the object stays alive for the
caller (matching `DereferenceRefCount(obj + 0xD0)` on the release paths). The
object's own critical section is still acquired at the same later point as before;
only the lifetime reference moved under the table lock.

### Patch Completeness Assessment

**CFR-gated behind `Feature_1207409977`.** The lock-synchronized lookup/AddRef runs
only when the flag is enabled; the original lockless path still ships when disabled.
Given the Critical, pre-auth nature, prioritize the July 2026 update and verify the
flag is enabled.

---

## Detection Guidance

**Behavioural.** SSTP connections driving concurrent handle use and teardown; UAF /
pool-corruption crashes in `sstpsvc!...` around `HfGetPointerFromHandle32` on
unpatched/flag-disabled builds.

**Config.** The fix is CFR-gated — confirm `Feature_1207409977` is enabled.

---

## References

- MSRC advisory — CVE-2026-50694 (Windows SSTP Remote Code Execution), released 2026-07-14, KB5101650.
- Full binary diff: `/data/patch_diffs/sstpsvc_dll-cve-2026-50694-ghidriff.md`
