Six Privilege Escalations and an Info Leak in Windows [Blackswan vulnerabilities]

We discussed this vulnerability during Episode 92 on 19 October 2021

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.

Bug #1: AlpcpCompleteDispatchMessage TOCTOU 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.

Bug #3: TcpIoControlEndpoint infoleak Code 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.

Bug #4: TcpIoControlEndpoint arbitrary read/write Code 0x18 would invoke TcpSetSecurityEndpoint, allowing you to get full control of the pointer for the security descriptor.

Bug #5: UdpSetSockOptEndpoint arbitrary increment The 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.

Bug #6: UdpSetSockOptEndpoint TOCTOU 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.

Bug #7: 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.