Seven vulnerabilities in Windows. Starts off with a lot of background information on Windows kernel I/O, how Time-of-Check Time-of-Use (TOCTOU) works, and an overview of Advanced Local Procedure Calling (ALPC), which is a set of high performance IPC syscalls. The important takeaways before reading into the vulnerabilities are:
- Windows ioctls can operate in three different modes:
- “Buffered”, where user data is copied into kernel controlled buffers.
- “Direct I/O”, where a usermode buffer is locked in memory and mapped to a kernel address.
- “Neither”, where the kernel will operate directly on a shared user mapping.
- Users of ALPC calls can optionally use I/O completion ports for processing asynchronous I/O requests.
This function copies a user-provided message header and body into a shared user memory region and operates directly on it. Because a user can write to it, there’s a TOCTOU where a user could overwrite a field such as the message length post-validation, allowing an out of bounds access.
Bug #2: Socket validation bypass
Normally, when sending socket I/O control requests, the request “codes” or commands are validated so users can’t call internal functions with dangerous values. However, if you create a socket with a transport name specified, you’ll get a special handle called a “TDX” (Transaction Driver) handle, which allows you to call
TdxIssueIoControlRequest function. This routine has no restrictions on user-provided codes, opening up a large attack surface for the next 4 bugs.
0x20 would invoke
TcpQuerySecurityEndpoint, which would return a pointer to the security descriptor from the kernel PagedPool and write it directly to the output buffer in userland. This also works with UDP address endpoints.
TcpIoControlEndpoint arbitrary read/write
0x18 would invoke
TcpSetSecurityEndpoint, allowing you to get full control of the pointer for the security descriptor.
UdpSetSockOptEndpoint arbitrary increment
SIO_RESERVED_1 code on UDP address endpoints would pass requests to
QimInspectAssociateQoS for quality of service functionality. Normally messages going to this function are translated by the AFD.sys driver, but here the user is given direct access, and can pass an arbitrary pointer for the endpoint. This can be leveraged as an arbitrary increment via abusing a refcount increment.
SIO_SET_QOS would call
QimInspectSetQos. In this case, the user-provided data is presumably validated, but it doesn’t properly lock the user buffer, so it’s vulnerable to a TOCTOU where the
ProviderSpecific buffer size can be increased post-allocation.
SIOCSMSFILTER in multicast filtering (ipv4/ipv6)
Similar to bugs 1 and 6, user-data is mapped into user mode shared memory, and the
gf_numsrc field is vulnerable to a TOCTOU condition, allowing overflow in the kernel NonPagedPool.