For the may 2019 security patch release, Microsoft included a patch for a RCE (remote command exec) bug in the remote desktop service (RDP).
This was to fix an exploit where an unauthenticated attacker would send “core-system” malformed and malicious RDP messages to the target server using system-level message service to the MS_T120 protocol of the target, causing the server to execute the
code as ring0, or administrator by utilizing a page 0 overwrite caused by a use-after-free vulnerability.
If the exploit was successful, then the attacker could execute arbitrary code with administrative privileges on the remote machine. The bug, which has been abused for a while now before released public and was provided a CVE of CVE-2019-0708.
The specific exploit was discovered in the way RDP utilizes shared session, specifically in the way the ITU-T+T.128 sharing protocol was implemented. The T.120 protocol is an os agnostic protocol, although used heavily for point-to-multipoint communication protocols for teleconferencing.
The basic premise of the vulnerability is that there is the ability to bind a static channel named “MS_T120” outside of its standard bucket.
This channel is normally only used internally by Microsoft components, and shouldn’t receive arbitrary messages from outsiders, but it did.
Although many (too many) components make up remote desktop service internals, multiple non-user privileged DLLs cross-call many kernel-mode drivers when an RDP session is called. Sending a specially crafted message to the RDP server can lead to a use-after-free vulnerability inside the ring0 (administrator) driver TERMDD.SYS.
Remote desktop utilizes SVC or “static virtual channels.” Normally. SVC is used for interprocess communication between the operating system (ring0, host) and the user (non-priv) for various components and user extensions, like shared printing.
The standard Microsoft RDP offers options like redirection (rdpdr) Clipboard sharing, (cliprp) and print spooler sharing as well.
An API exists that even allows users to write modules themselves to use with other channels.
When an RDP session is started, the operating system uses two default modules (both loaded from MS_T120) just to initiate a basic RDP session. Under normal, non-exploitive standards, a normal RDP client was not ever expected to be able to generate or craft other systems-level calls to other RDP hosts as these methods were always initiated internally by the RDP core system when a connection is established.
The exploitation of MS_T120 was performed by sending a non-nla series of messages to the RDP protocol against the target of your choosing. Sending these systems only messages are read by the victim’s machine by RDPWSX.sll which would open a thread loop into a function for IoThread
and then waits for the input and output to get passed to the ring0 (administrator) driver for TERMDD.sys.
After the attacker performs the multi-step server and client side handshake required to create a normal RDP session he/she then sends messages to the individual channels you’ve requested to bind, specifically the malicious channel at page 0.
The MS_T120 channel messages are managed in the user-mode component RDPWSX.DLL. This DLL spawns a thread which loops in the function ioThreadRead(). This waits (and writes to the page table for RDP) for new messages from network traffic that gets funneled through the TERMDD.SYS driver.
Practical exploitation of this waits until a pointer in the I/O hits a function called CTS (control channel structure), and then the data sent by the attacker is saved in a high-level pointer table called the channel pointer. Because every RDP connections start with the request to look at the pointer table it reads
the attacker’s payload first rather than the normal initiate functions expected.
The attacker, once successfully exploited the RDP stack, takes advantage of a use after free vulnerability inside of the termdd.sys kernel driver and results in the RDP service to read the data pointed to by the MS_T120 system that the attacker controls from remote.
Once the payload is delivered to the remote host, the attacker may then execute code on the target with system privileges.