# CVE-2026-21236 — afd.sys `AfdSanConnectHandler` Heap-Based Buffer Overflow

---

## Summary

| **Product** | Microsoft Windows — `afd.sys` (Ancillary Function Driver for WinSock) |
|---|---|
| **Vendor** | Microsoft Corporation |
| **Severity** | CVSS v3.1 **7.8 (High)** |
| **CVSS Vector** | `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H` ([MSRC](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-21236)) |
| **CVE Title** | Windows Ancillary Function Driver for WinSock Elevation of Privilege Vulnerability |
| **CWE** | CWE-122 (Heap-based Buffer Overflow), CWE-787 (Out-of-bounds Write) |
| **Affected Versions** | Windows 10 (1607+), Windows 11 (23H2/24H2/25H2), Windows Server 2012–2025 |
| **Tested Version** | Windows 11 24H2 — afd.sys 10.0.26100.7623 (pre, KB5074109) vs 10.0.26100.7824 (post, KB5077181) |
| **Impact** | Local EoP — authenticated local attacker corrupts kernel pool memory → SYSTEM |
| **Exploitability (MSRC)** | "Exploitation Unlikely" — practical trigger requires **Windows Server** with SAN/RDMA components |
| **PoC Available** | NCC Group published a full analysis + PoC walkthrough (Python, WinDbg-verified BSOD); no public weaponised exploit |
| **Patch Date** | February 2026 Patch Tuesday — KB5077181 |
| **Public analysis** | [NCC Group / Fox-IT, Emily Liu](https://www.fox-it.com/media/e23bjwvh/ncc-group-vulnerability-analysis-of-cve-2026-2136.pdf) |

---

## Root Cause

`afd.sys` still carries the legacy **SAN (System Area Network / Windows
Sockets Direct, RDMA)** code path for backwards compatibility. Two IOCTL
handlers cooperate across two different socket handles:

1. **`AfdSuperAccept`** — called on a *listener* SAN endpoint. It parses a
   user-controlled `Type3InputBuffer` whose length fields
   (`ReceiveDataLength`, `RemoteAddressLength`, …) are sanity-checked, then
   allocates an MDL of user-influenced `TotalLength` via `IoAllocateMdl` +
   `MmProbeAndLockPages`. This is the **destination buffer**.

2. **`AfdSanConnectHandler`** — called on a *connecting* SAN endpoint. It
   copies the connect request's address payload into the listener's MDL
   buffer (`MmMapLockedPages`). The **copy length is read from the
   user-controlled input buffer (`*_Src`) and was never checked against the
   size of the buffer allocated by `AfdSuperAccept`**.

Because the attacker controls the allocation size (via `AfdSuperAccept`), the
copy size, and the copied bytes (via `AfdSanConnectHandler`), a copy size
larger than the allocation produces a fully controlled **kernel heap/pool
overflow** (in NCC's demo: 0x1000-byte buffer, 0x2002-byte copy, classic
`'A'`*0x1000 + `'B'`*0x1002 pattern observed in WinDbg over the MDL's mapped
VA).

### The patch (verified in our ghidriff diff, 7623 → 7824)

Behind WIL feature flag `Feature_3923194169`, the copy length is now clamped
against the destination buffer's size field (`*(uint*)(lVar15 + 0x18)`,
sourced from the IRP stack) before **both** copy sites:

```c
// post-patch 10.0.26100.7824 — clamp added before memcpy
if ((int)(uVar27 + 4) < (int)((uVar5 & 0xffff) - 8)) uVar27 = uVar27 + 4;
else                                                uVar27 = (short)uVar5 - 8;
memcpy(_Dst + 2, _Src, _Size);        // clamped
```

`AfdSuperAccept` and `AfdRestartSuperAcceptGetAddress` were also touched in
the same change set (call-site/context alignment).

---

## Reaching the bug — userspace call flow

> **Platform gate:** `AfdSanCreateHelper` checks `MmIsThisAnNtAsSystem()` —
> SAN endpoint creation succeeds only on **Windows Server** SKUs with SAN
> components installed. On Windows 10/11 client the vulnerable code exists but
> the endpoint cannot be created; the IOCTL returns an error. This is why
> MSRC rates exploitation "Unlikely".

AFD has no documented userspace SAN API; all interaction is raw IRP traffic
(NCC's approach, building on Akamai's prior AFD research):

```
ntdll!NtCreateFile("\\Device\\Afd\\Endpoint", EA = "AfdSwOpenPacket")
        │                                   ← SAN endpoint (NOT "AfdOpenPacketXX")
        ▼
afd!AfdSanCreateHelper ── MmIsThisAnNtAsSystem() gate (Server only)
        │
        ├─► [handle A] SAN listener endpoint
        │       NtDeviceIoControlFile(hA, IOCTL 0x12003 AfdBind)      ← bind to address
        │       NtDeviceIoControlFile(hA, AfdSuperAccept)             ← allocates MDL
        │                                  buffer of attacker-chosen TotalLength
        │
        └─► [handle B] SAN connecting endpoint
                NtDeviceIoControlFile(hB, IOCTL 0x12003 AfdBind)
                NtDeviceIoControlFile(hB, IOCTL 0x120E2)  ──► afd!AfdSanConnectHandler
                                   │                            memcpy(listener_MDL + off,
                                   │                            user_src, *_Src)  ← BUG
                                   ▼
                     pool overflow with attacker size + contents → bugcheck
```

| Element | Value |
|---|---|
| Device | `\Device\Afd\Endpoint` via `NtCreateFile` with EA name `AfdSwOpenPacket` (SAN) |
| IOCTL — bind | `0x12003` (`AfdBind`) |
| IOCTL — vulnerable handler | `0x120E2` (`AfdSanConnectHandler`) |
| Supporting call | `AfdSuperAccept` on the listener handle (creates the undersized buffer) |
| Privileges | Local authenticated user on Windows Server with SAN/RDMA present |
| Detection surface | `NtCreateFile` on `\Device\Afd\Endpoint` with EA `AfdSwOpenPacket` is *extraordinarily* rare on real systems — a high-fidelity hunt/telemetry signal on its own |

---

## PoC policy (deliberate)

No new PoC is shipped for this CVE:

1. NCC Group's paper already contains a complete, debugger-verified PoC
   walkthrough (Python + WinDbg) — duplicating it adds nothing.
2. A trigger only fires on **Windows Server**; it cannot be crash-validated on
   a Windows 11 client, and unvalidated kernel PoCs are worse than none.
3. For blue-team purposes the **signal is the attempt, not the crash**: SAN
   endpoint creation (EA `AfdSwOpenPacket`) and IOCTL `0x120E2` have no
   legitimate userspace callers on modern systems.

See [poc_cve_2026_21241.c](poc/poc_cve_2026_21241.c) for the *client-reachable*
afd.sys bug from the same Patch Tuesday (CVE-2026-21241), which does produce a
validatable crash.

---

## Detection engineering

- **Sysmon/ETW (process)**: any process opening `\Device\Afd\Endpoint` with an
  Extended Attribute named `AfdSwOpenPacket` (visible via kernel
  Object/IoCreateFile tracing, e.g. Microsoft-Windows-Kernel-File or a
  minifilter). On clients this should be near-zero prevalence.
- **IOCTL auditing**: IOCTL `0x120E2` to AFD endpoints. Requires driver-level
  telemetry (ETW kernel IOCTL providers / EDR), but is unambiguous.
- **YARA (memory/disk)**: PoCs and tooling embed the EA string
  `AfdSwOpenPacket` and the IOCTL constant `0x120E2` — both are stable,
  low-collision indicators.
- **Crash forensics**: bugchecks in `afd!AfdSanConnectHandler` /
  `afd!AfdSuperAccept` on pre-KB5077181 Server builds.

## References

- [MSRC — CVE-2026-21236](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-21236)
- [NCC Group / Fox-IT — Vulnerability Analysis of CVE-2026-21236 (PDF)](https://www.fox-it.com/media/e23bjwvh/ncc-group-vulnerability-analysis-of-cve-2026-2136.pdf)
- [NVD — CVE-2026-21236](https://nvd.nist.gov/vuln/detail/CVE-2026-21236)
- [Akamai — AFD reverse engineering (referenced groundwork)](https://leftarcode.com/posts/afd-reverse-engineering-part1/)
- Diff doc: [afd_sys-kb5077181.md](afd_sys-kb5077181.md)
