CVE-2025-60719 - Windows Ancillary Function Driver for WinSock Elevation of Privilege Vulnerability

Ghostbyt3 Ghostbyt3
Table of Contents

CVE-2025-60719: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-60719
Vulnerability Type: Untrusted Pointer Dereference
Driver Version: afd.sys - 10.0.26100.7019

Vulnerability analysis

The Windows Ancillary Function Driver for WinSock is a kernel-mode component that implements low-level socket handling for Windows. It’s a critical system driver that serves as the bridge between user-mode applications and the kernel networking stack. This is a Windows component that is responsible for serving the Winsock API.

The vulnerability exists in the following functions, which all follow a similar methodology: AfdGetInformation, AfdSocketTransferEnd, and AfdSocketTransferBegin.

By examining AfdGetInformation, which is used to retrieve information about a socket,

Line 81 – The function checks whether Src is not equal to 5. Here, Src corresponds to the AFD_INFORMATION structure provided via the input buffer. The vulnerability is associated with the AFD_MAX_PATH_SEND_SIZE class/type, so the InformationType must be set to 5 to reach the vulnerable code path. If this condition is met, execution jumps to line 171.

Line 171 – At this point, v11 represents an AFD_ENDPOINT structure. The code performs three checks in order to enter the conditional statement:

  • It checks whether AFD_ENDPOINT->InLine is FALSE.
  • a5 represents the buffer length, and the code verifies that it is greater than 0x10.
  • It checks whether AFD_ENDPOINT->State is either 3 (AfdEndpointStateConnected) or 4 (AfdEndpointStateCleanup) (the exact semantic meaning of these states is inferred and not fully confirmed).

Line 178 – Once all conditions are satisfied, the function calls IoAllocateMDL() to allocate a Memory Descriptor List (MDL) for mapping the user-supplied buffer. The buffer size is passed as the second argument (a5).

Line 193 – The specified virtual pages are then locked in memory.

Line 197 – Finally, the function calls AfdIssueDeviceControl(), which sends an IRP to the specified device object.

The race window exists between the AFD_ENDPOINT state checks and the call to AfdIssueDeviceControl(). Since AfdGetInformation() is used to query socket information, if the socket is unbound (released) after the endpoint checks but before the IOCTL is issued, the IRP may dereference pointers that have already been freed. This can lead to a use-after-free condition and potentially trigger a system bugcheck.

image.png image.png

Exploit

Tested on: Windows 11 24H2 POC: https://github.com/ghostbyt3/WinDriver-EXP/blob/main/CVE-2025-60719/POC/main.cpp

IMG

IMG1

Patch Analysis

Analyzing the patched version of the AfdGetInformation() function, new functions have been introduced to address this issue. First, the AfdPreventUnbind() function (line 219) is called with the AFD_ENDPOINT. This function ensures that the socket cannot be unbound during the critical section. Next, the function calls AfdIssueDeviceControl() (line 242), which sends an IRP to the specified device object. After this operation completes, another newly introduced function, AfdReallowUnbind() (line 251), is called to re-enable the unbind operation for the socket. This sequence prevents the socket from being unbound while the IOCTL request is in progress, thereby eliminating the race condition.

IMG2

References: