# CVE-2026-56188 — Windows NetBIOS-over-TCP/IP `netbt.sys` Connection-Teardown Race → Unauthenticated Network RCE

---

## Summary

| | |
|---|---|
| **Product** | Windows — `netbt.sys` (NetBIOS over TCP/IP / "Windows Server Network driver") |
| **CVE ID** | CVE-2026-56188 |
| **Impact** | Remote Code Execution (unauthenticated, network) |
| **MSRC severity** | Critical |
| **CVSS** | 9.8 / 8.5 — `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition') |
| **Delivery** | Network — specially crafted traffic to the server (no authentication) |
| **KB / Fixed build** | KB5101650 — `netbt.sys` 10.0.26100.8875 (Win11 24H2 / Server 2025 x64) |
| **Patch Date** | July 14, 2026 (2026-Jul) |
| **Pre-patch binary** | `netbt.sys` 10.0.26100.8737 (KB5095093) — SHA256 `57b9e51d0d72f00ead8f828cb5f3c148c0ea936ae6b663c808f8bb462be6c444` |
| **Post-patch binary** | `netbt.sys` 10.0.26100.8875 (KB5101650) — SHA256 `7ee6c3d274c3dbd7a5ee16268db161e8a46b08eb34b25b90b7add2ea3ca079d7` |
| **Feature flag** | `Feature_1180933432` — **the fix is CFR-gated** (same flag as the SMB `srvnet` CVE-2026-57089 — a coordinated network-driver hardening) |
| **Exploitability** | Exploitation More Likely; not publicly disclosed; not exploited (per MSRC) |

---

## Product Description

`netbt.sys` is the Windows **NetBIOS over TCP/IP (NetBT)** transport driver. It manages
NetBT **lower connections** (the TCP connections underlying NetBIOS sessions), which are
created (`NbtOpenAndAssocConnection`), referenced/dereferenced
(`NbtDereferenceLowerConnection`, `NbtDeleteLowerConn`), and torn down through a family
of disconnect/cleanup routines (`NbtDisconnect`, `TdiDisconnect`, `TcpDisconnect`,
`DisconnectLower`, `DelayedCleanupAfterDisconnect`, `DisconnectDone`, `OutOfRsrcKill`)
while inbound network data is delivered via the TDI receive path
(`TdiReceiveHandler`, `NTReceive`, `NbtIndicateDataToClient`).

---

## Vulnerability Summary

A NetBT lower-connection object is shared between the **connection-teardown** paths and
the **in-flight receive/send** paths. Pre-patch, these were **not adequately
synchronized**: a disconnect/cleanup could dereference and free the connection object
while a receive/indicate operation on the same connection was still in progress — a race
(CWE-362) that corrupts or reuses the freed connection state. Because NetBT processes
**attacker-supplied network traffic without authentication** (`AV:N`, `PR:N`, `UI:N`),
the race is a remote code-execution primitive (Microsoft rates it **Critical, 9.8**).

> Confirmation level: this July update is a **broad connection-lifecycle rework** (30
> code-changed + 58 modified functions) dominated by added **spinlock serialization**
> (~193 `KeAcquireSpinLock` sites) across the disconnect/dereference/cleanup routines,
> all gated behind `Feature_1180933432`. The isolable mechanism is that lower-connection
> teardown and dereference are now performed **under the connection spinlock with state
> validation** rather than racing in-flight I/O; stated at confirmed-changed level.

---

## Prerequisites and Constraints

- Network, unauthenticated (`AV:N`, `AC:L`, `PR:N`, `UI:N`): send crafted NetBT traffic
  to the server (NetBIOS session service, TCP/139).
- Race a connection teardown against an in-flight receive/indicate on the same NetBT
  lower connection.
- Result: the connection object is dereferenced/freed while still in use.

---

## Vulnerability Details

### Root Cause

The NetBT lower-connection object's teardown/dereference was not serialized against
concurrent receive/send processing, so a disconnect could free the object while another
path still referenced it.

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

The `NBT_LOWERCONNECTION` object stores its reference count at `+0x14`, the bidirectional
link to the upper connection at `+0x18`, and a **per-connection** spin lock at `+0x68`.
Pre-patch, `NbtDereferenceLowerConnection` took **only the per-connection lock** (`+0x68`)
around the interlocked decrement; on the final release it cleared both sides of the
connection pair and queued the object for deferred freeing. The **module-global** lock was
already used by other connection-state routines (`CleanUpPartialConnection`,
`CleanupConnectingState`, `CountUpperConnections`) — `NbtDereferenceLowerConnection` simply
was not among its users.

The fix, gated behind the CFR flag (`Feature_1180933432` in the analysed ghidriff), extends
that **same module-global lock** to `NbtDereferenceLowerConnection` (and additional
teardown call sites), so the dereference is now serialized against those other
connection-state routines rather than racing them:

```c
// NbtDereferenceLowerConnection (10.0.26100.8875) — PATCHED (from the diff)
if (feature_enabled) {
    if (!caller_holds_global_lock)                 // 3rd param signals the caller already holds it
        irql = KeAcquireSpinLockRaiseToDpc(&g_ModuleGlobalLock);   // *** module-global lock (new here) ***
    KeAcquireSpinLockAtDpcLevel((PKSPIN_LOCK)(conn + 0x68));       // per-connection lock (already in PRE)
    if (InterlockedExchangeAdd((int*)(conn + 0x14), -1) != 1) {    // interlocked decrement (unchanged)
        KeReleaseSpinLockFromDpcLevel((PKSPIN_LOCK)(conn + 0x68));
        ...
    }
    // final release: clear both sides of the pair, queue deferred free
}
```

The interlocked decrement itself is unchanged — the fix changes the **locking discipline**
around it (adding the global lock, and threading a "caller already holds the global lock"
flag through the third parameter). Note also that when the feature is enabled the legacy
`state = 1000` poison-write at `conn + 0x14` is **no longer performed** (it remains only on
the pre-patch / flag-disabled path). With the dereference and teardown serialized under the
module-global lock shared with the other connection-state routines, a disconnect can no
longer free the connection while a receive is in flight, closing the race.

> Feature-flag note: the analysed ghidriff gates this change with `Feature_1180933432`; an
> independent decompilation of the same fix cites `Feature_1248042296`. The mechanism
> (adding the module-global lock) is the same either way.

### Patch Completeness Assessment

**CFR-gated behind `Feature_1180933432`.** The serialized teardown runs only when the
flag is enabled; the original unsynchronized path still ships when disabled. Verify
`Feature_1180933432` is enabled to confirm the fix is live. Given unauthenticated network
RCE, apply KB5101650 or later and restrict NetBIOS (TCP/UDP 137–139) exposure regardless.

---

## Detection Guidance

**Behavioural.** Use-after-free / pool-corruption bugchecks in `netbt!NbtDisconnect` /
`NbtDereferenceLowerConnection` / `DelayedCleanupAfterDisconnect` / `TdiReceiveHandler`
on unpatched/flag-disabled builds, correlated with bursts of NetBIOS session
connect/disconnect activity. Restrict NetBT (TCP 139, UDP 137/138) to trusted networks;
disable NetBIOS over TCP/IP where unused.

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

---

## References

- MSRC advisory — CVE-2026-56188 (Windows Server Network driver Remote Code Execution), released 2026-07-14, KB5101650.
- Related: CVE-2026-57089 (SMB `srvnet.sys`) shares the `Feature_1180933432` network-driver hardening.
- Full binary diff: `/data/patch_diffs/netbt_sys-cve-2026-56188-ghidriff.md`
