Skip to content

CVE-2023-21768

AFD WinSock, missing ProbeForWrite allows kernel write-what-where via IO ring

Summary

Field Value
Driver afd.sys
Vulnerability Class User Boundary Validation
Vulnerable Build 10.0.22621.608 (KB5020044)
Fixed Build 10.0.22621.1105 (KB5022303)
Exploited ITW No

The Story

CVE-2023-21768 is one of the cleanest kernel exploitation primitives in the KernelSight corpus. A single missing ProbeForWrite call in afd.sys produces a deterministic write-what-where primitive with no race condition, no heap layout dependency, and no information leak requirement beyond standard techniques. chompie1337's PoC demonstrated reliable SYSTEM escalation using the I/O Ring API introduced in Windows 11.

The bug highlights a fundamental truth about Windows kernel development: even in a mature, heavily audited driver like afd.sys, a single missing validation check can produce a complete privilege escalation.

Affected Functions

  • AfdRioValidateRequestBuffer
  • AfdNotifyRioRemoveCompletion

The Missing ProbeForWrite

The Ancillary Function Driver handles socket operations for user-mode applications. In the code path that manages Registered I/O (RIO) completion notifications, afd.sys writes a completion status to a buffer address supplied by user mode. Normally, the driver must call ProbeForWrite on any user-supplied pointer before writing to it, verifying that the target address falls within user-mode address space and is writable.

In the vulnerable code path, this probe was omitted. Without it, a kernel-mode address can be supplied as the completion target buffer pointer. The driver writes the I/O completion status (a value influenced through the socket operation) directly to this kernel address. The destination address is controlled via the completion buffer pointer; the value written is controlled via the I/O status result.

AutoPiff categorizes this as user_boundary_check with detection rules:

  • added_probe_for_write
  • added_probe_call

From IO Ring to SYSTEM

chompie1337's PoC demonstrates the exploitation using the Windows 11 I/O Ring API. The attacker creates an IO ring via CreateIoRing, registers a buffer specifying a kernel-mode address as the completion target via BuildIoRingRegisterBuffers, and performs an AFD socket operation that triggers the completion write path. The kernel writes the I/O status to the specified kernel address without validation.

The PoC overwrites the current process's token pointer in the EPROCESS structure with the SYSTEM process token, escalating from a standard user to SYSTEM. Target addresses are obtained through standard information leak techniques.

What makes this exploitation noteworthy is its determinism. The write occurs exactly once to the exact address specified. No race condition to win, no heap layout to control. The syscall pattern (IO ring create, buffer register, AFD operation) produces the write-what-where reliably on every attempt.

Patch Analysis

The patch shipped in KB5022303 (build 10.0.22621.1105) added ProbeForWrite calls before writing to user-supplied buffer addresses in the I/O completion path within afd.sys. If the address falls in kernel space, the probe raises an exception caught by the driver's exception handler, preventing the write.

AutoPiff detects this patch pattern via the added_probe_for_write and added_probe_call rules, which identify the introduction of new ProbeForWrite invocations in the patched binary that were absent in the vulnerable build.

Detection

YARA Rule

rule CVE_2023_21768_AFD {
    meta:
        description = "Detects vulnerable version of afd.sys (pre-patch)"
        cve = "CVE-2023-21768"
        author = "KernelSight"
        severity = "high"
    strings:
        $mz = { 4D 5A }
        $driver_name = "afd.sys" wide ascii nocase
        $vuln_build = "10.0.22621.608" wide ascii
        $func_validate = "AfdRioValidateRequestBuffer" ascii
        $func_notify = "AfdNotifyRioRemoveCompletion" ascii
    condition:
        $mz at 0 and $driver_name and $vuln_build and ($func_validate or $func_notify)
}

ETW Indicators

Provider Event / Signal Relevance
Microsoft-Windows-AFD RIO completion events Registered I/O completion notification path where the missing ProbeForWrite allows kernel address writes
Microsoft-Windows-Kernel-Audit Token modification events Detects the EPROCESS token overwrite used to escalate from standard user to SYSTEM
Microsoft-Windows-Security-Auditing Event ID 4672 (Special privileges assigned) Low-privilege process acquiring SYSTEM-level privileges immediately after IO ring operations
Microsoft-Windows-Security-Auditing Event ID 4688 (Process creation) Child process launched with SYSTEM token from an unprivileged parent following AFD socket activity
Microsoft-Windows-Kernel-Process IO ring registration events Abnormal IO ring buffer registrations specifying kernel-mode addresses as completion targets

Behavioral Indicators

  • A user-mode process creates an IO ring via CreateIoRing, registers a buffer with BuildIoRingRegisterBuffers, and then performs an AFD socket operation that triggers a completion write to a kernel-mode address
  • No pool spray or heap grooming is needed; the write-what-where primitive is deterministic, so the syscall pattern (IO ring create, buffer register, AFD operation) is a reliable detection signature
  • The process calls NtDeviceIoControlFile on an AFD socket handle with I/O completion targeting an address above the user/kernel boundary (typically above 0x7FFFFFFFFFFF)
  • Token replacement in the current process's EPROCESS structure: the process transitions from a standard user token to SYSTEM without any legitimate elevation mechanism
  • Post-exploitation, the process (or a newly spawned child) operates with SYSTEM integrity, often performing actions inconsistent with its original user context

Broader Significance

CVE-2023-21768 is the textbook case for the missing ProbeForWrite vulnerability class. It demonstrates that even in 2023, a single omitted validation check in a core Windows driver can produce a clean, deterministic privilege escalation. The exploitation is so straightforward that it became widely reproduced and studied, making it one of the most educational Windows kernel exploitation examples of the year. For the AFD attack surface specifically, see the AFD Deep Dive for the complete pattern analysis.

References