CVE-2019-0708: A Comprehensive Analysis of a Remote Desktop Services Vulnerability

May 28, 2019 | Guest Blogger

In the May 2019 patch cycle, Microsoft released a patch for a remote code execution bug in their Remote Desktop Services (RDS). A remote, unauthenticated attacker can exploit this vulnerability by sending crafted RDP messages to the target server. Successful exploitation can result in the execution of arbitrary code with administrative privileges – meaning the bug is wormable. While our initial research into this bug focused on mitigations and protections, Pengsu Cheng, Kamlapati Choubey, and Saran Neti of the Trend Micro Security Research Team worked to complete a thorough analysis of the vulnerability. The following is an excerpt from their Trend Micro Vulnerability Research Service report covering CVE-2019-0708, with a few minimal modifications.


The Vulnerability

Microsoft Remote Desktop Services (formerly known as Terminal Services) allows users to open interactive Windows sessions remotely. Remote Desktop Services provides similar functions to those of terminal-based environments where multiple terminals (clients) can be connected to a single host (server). A remote user can log on to a remote host and access data, run applications, etc. on the host computer. The remote desktop connection defaults to communicating with a remote server using Remote Desktop Protocol (RDP) over port 3389/TCP.

 RDP specifies how multiple conference participants view and collaborate on shared programs. The protocol is a Microsoft extension of the ITU-T T.128 Application Sharing Protocol. The protocol utilizes other services provided by lower tier protocols in the T.120 standard, such as the T.124 Generic Conference Control (GCC), T.122 Multipoint Communication Services (MCS), etc.

An RDP connection starts with the connection sequence messages, defined by Remote Desktop Protocol: Basic Connectivity and Graphics Remoting (MS-RDPBCGR) protocol, as follows [1]:

The format of each message can be found in [1]. The vulnerability is related to the “MCS Connect Initial and GCC Create” request.

The “MCS Connect Initial and GCC Create” request sent from client to server after receiving the “X.224 Connection Confirm” response. The “MCS Connect Initial and GCC Create” request contains security-related information, virtual channels creation information, and other supported RDP client capabilities. The structure of the “MCS Connect Initial and GCC Create” request is as follows [1]:

All multi-byte integers are in little-endian byte-order, except for the tpktHeader field.

•      An X.224 layer, generally, can have several PDU types and be composed of any lengths, but an “MCS Connect Initial and GCC Create” packet has a 3-byte x224 structure.
•      The mcsCi structure is a T.125 MULTIPOINT-COMMUNICATION-SERVICE Connect-Initial PDU, which is encoded using ASN.1 DER. Its structure can be found in [4].
•      The gccCrq structure is a T.124 Generic Conference Control ConnectData structure; its structure can be found in [5].

Settings Data Blocks is a concatenation of one or more Settings Data Block, each of which has the following format:

Various types of Settings Data Block exist including CS_CORE (0xC001), CS_SECURITY (0xC002), CS_NET (0xC003), and so on [1].

The tpktHeader field has the following structure [2]:

All multi-byte integers within tpktHeader are in big-endian byte-order. version must be 0x03 and tpktLength specifies the length of the entire packet. The vulnerability is related to the CS_NET Settings Data Block, also called clientNetworkData.

The clientNetworkData field contains a list of requested virtual channels. The structure of the clientNetworkData field is as follows [3]:

The CS_NETHeader field for clientNetworkData is 0xC003, which in little-endian is \x03\xc0. The channelCount field indicates requested static virtual channels. The channelNamen (where n is 1,2,.., N) field defines an 8-byte null-terminating name of the channel and the channelOption_n field specifies the attributes of the channel.

The RDP protocol supports static virtual channels, which are intended to be used as communication links for various RDP components and user extensions. These channels are known by their 8-byte channel names, and include standard Microsoft-supposed channels such as “rdpdr” (Redirection), “rdpsnd” (Sound), “cliprdr” (Clipboard sharing) etc. Users can write modules using the RDP API to support other channels. In addition to the above channels, Microsoft creates two channels by default: MS_T120 (used for RDP itself) and CTXTW (used in Citrix ICA). Clients are not expected to create these channels over the network; instead, these channels are initialized internally by Windows RDP system when a connection is established.

Channels are created using termdd!IcaCreateChannel(), which first checks whether the specified named channel exists, and if not allocates a channel structure to create it. A pointer to the channel structure, which structure we shall call ChannelControlStructure, is stored within a table, which we shall call ChannelPointerTable. All RDP connections start with the ChannelPointerTable looking as follows (the first five slots are not user-controlled and hence not shown. Instead Slot Number 0 is taken as the first client-writable channel):

In the above table, each slot can store a ChannelControlStructure pointer, with ones marked Empty storing a NULL pointer. When an RDP client connects and opens channels by specifying them in clientNetworkData, the corresponding ChannelControlStructures are created and their pointer stored in the ChannelPointerTable starting at Slot 0. Note that CTXTW is always present in Slot 7, and MS_T120 in Slot 0x1F.

A use-after-free vulnerability exists in Microsoft Windows RDP kernel driver, termdd.sys. Upon receiving the MCS Connect Initial and GCC Create packet containing clientNetworkData, ChannelControlStructures for channels specified therein are created. If a channel with name `MS_T120\x00` is specified (e.g., in Slot 10), termdd!IcaCreateChannel() calls termdd!IcaFindChannelByName() and returns the ChannelControlStructure pointed to by the MS_T120 structure in Slot 0x1F. This pointer (same as the one in Slot 0x1F) is stored in the user specified slot (in this example, Slot 10), within the function termdd!IcaBindVirtualChannels(). Next, when the channels are opened using MCS Channel Join Request, the MS_T120 channel is also opened successfully. If an attacker then sends crafted data into the MS_T120 channel, termdd.sys attempts to respond to the message by sending an error message and closing the channel using termdd!IcaCloseChannel(), which in turn calls termdd!_IcaFreeChannel(), which frees the MS_T120 ChannelControlStructure and clears the pointer at the user-controlled slot (Slot 10 in the running example) in ChannelPointerTable. However, the same pointer in Slot 0x1F isn't cleared. Subsequently, when the connection terminates, RDPWD!SignalBrokenConnection() is invoked, which in turn calls termdd!IcaChannelInputInternal() and attempts to write to the freed ChannelControlStructure using the pointer at Slot 0x1F. This leads to a use-after-free condition. 

A remote, unauthenticated attacker can exploit this vulnerability by establishing an RDP connection with the target server whilst opening an MS_T120 channel, and sending crafted data to it. Successful exploitation will result in the attacker being able to execute arbitrary code with Administrative (kernel-level) privileges.

Source Code Walkthrough

The following code snippet was taken from termdd.sys version 6.1.7601.24056. Comments added by Trend Micro have been highlighted.

 To detect an attack exploiting this vulnerability, the detection device must monitor and parse traffic on assigned port, which by default is 3389/TCP. 

An RDP connection starts with the connection sequence messages, defined by Remote Desktop Protocol: Basic Connectivity and Graphics Remoting (MS-RDPBCGR) protocol, as follows [1]:

Note:

•      This detection guidance is concerned with the message “MCS Connect Initial and GCC Create.”
•       RDP has two types of encryption: A custom RDP Encryption, and one using TLS. In the former case, “MCS Connect Initial and GCC Create” is in plaintext, while in the latter case, “MCS Connect Initial and GCC Create” is the first packet sent by an RDP client after TLS is established.
•      After the exchange of the first request and response, the traffic may be encrypted using TLS. The easiest way to determine this is by checking whether the second incoming packet to the server begins with "\x16\x03" (the TLS record type, and the high version number of a TLS Client Hello).

The detection device must be capable of inspecting and analyzing RDP communication between the RDP server and an RDP client. If the RDP communication uses TLS, the detection device must decrypt the traffic before proceeding through the next steps.

The detection device must look for an incoming “MCS Connect Initial and GCC Create” request. The structure of the “MCS Connect Initial and GCC Create” request is as follows [1]:

All multi-byte integers are in little-endian byte-order, except for the tpktHeader field.

•      An X.224 layer, generally, can have several PDU types and be composed of any lengths, but an “MCS Connect Initial and GCC Create” packet has a 3-byte x224 structure.
•      The mcsCi structure is a T.125 MULTIPOINT-COMMUNICATION-SERVICE Connect-Initial PDU, which is encoded using ASN.1 DER. Its structure can be found in [6].
•      The gccCCrq structure is a T.124 Generic Conference Control ConnectData structure; its structure can be found in [5].

Settings Data Blocks is a concatenation of one or more Settings Data Block, each of which has the following format:

Various types of Settings Data Block exist including CS_CORE (0xC001), CS_SECURITY (0xC002), CS_NET (0xC003), and so on [1].

If an “MCS Connect Initial and GCC Create” request is found, the detection device must inspect each Settings Data Block and look for one with type CS_NET (0xC003). Such a Settings Data Block is called clientNetworkData, and has the following structure:

If clientNetworkData is found, the detection device must iterate through each channelName_n (where n is 1,2..,N) and check whether the value of any channelName_n field contains the case-insensitive string “MS_T120”. If such a channel is found, the traffic should be considered malicious; an attack exploiting this vulnerability is underway.

Triggering the Vulnerability

When the vulnerability is triggered while a debugger is attached to the target system, the following bugcheck occurs:

Conclusion

When Microsoft patched this vulnerability for their supported OSes, they made the decision to also release patches for the now unsupported Windows XP and Windows Server 2003 systems. That’s an indication of how severe they believe this vulnerability to be. There has also been some talk of active exploitation detected, but there’s definitely no doubting the exploitability of this vulnerability. This bug clearly earns its Critical rating, and affected systems should be patched as soon as possible. For those still on Windows XP or Server 2003, this is yet another reminder to get an upgrade plan in place. Microsoft may have released patches for this vulnerability, but chances of them releasing future patches for these now ancient systems lowers with each passing release.

Please note that there are two vulnerable functions in termdd.sys fixed by the Microsoft patch, IcaBindVirtualChannels() and IcaReBindVirtualChannels(). These two functions expose two different but similar attack vectors. Our analysis focused on the attack vector exposed by IcaBindVirtualChannels() .

Special thanks to Richard Chen, Pengsu Cheng, Kamlapati Choubey, and Saran Neti of the Trend Micro Security Research Team for providing such a thorough analysis of this bug. We certainly hope to see more vulnerability breakdowns from them in the future.

Until then, follow the ZDI team for the latest in exploit techniques and security patches.

References:

[1] [MS-RDPBCGR]:Remote Desktop Protocol: Basic Connectivity and Graphics Remoting, https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-RDPBCGR/[MS-RDPBCGR].pdf
[2] Network-specific data protocol stacks for multimedia conferencing, ITU-T Recommendation T.123, https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.123-200701-I!!PDF-E&type=items
[3] Client Network Data (TS_UD_CS_NET), Microsoft, https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/49f99e00-caf1-4786-b43c-d425de29a03f
[4] T.125, Multipoint communication service protocol specification, ITU, https://www.itu.int/rec/T-REC-T.125
[5] T.124, Generic Conference Control, ITU, https://www.itu.int/rec/T-REC-T.124
[6] Client Network Data (TS_UD_CS_NET), Microsoft, https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/49f99e00-caf1-4786-b43c-d425de29a03f