Explain Like I’m 5: Remote Desktop Protocol (RDP)
Table of Contents
- RDP Connection
- Connection Sequence | Basic Input and Output
- Channels in RDP | Data Compression
- RDP Security | Recent RDP Vulnerabilities
RDP is an extremely popular protocol for remote access to Windows machines. In fact, there are more than 4.5 million RDP servers exposed to the internet alone, and many more that are accessible from within internal networks.
The importance of knowing and understanding RDP has never been greater – especially in light of the recent critical vulnerabilities that were found in the protocol. It is now essential knowledge that is absolutely crucial for everyone in the security industry. RDP is a complex protocol with many extensions and the potential of finding new critical bugs is still high. This is why the security industry needs to educate itself about it.
RDP is relevant now more than ever, having Microsoft’s Azure and Hyper-V platforms using it as the default remote connection protocol and having the interest in this protocol by attackers rise, both as an initial infection vector and as a propagation method.
Since we weren’t able to find a digestible overview of this protocol, in this article we’ll walk through the basics of RDP, how they work, and how some of the critical vulnerabilities found in RDP fit into the bigger picture of an actual RDP connection. Our hope is that you’ll walk away with a basic understanding of the protocol so you can continue reading and researching further about the protocol for any future needs.
RDP: The Basics
“The Microsoft Remote Desktop Protocol (RDP) provides remote display and input capabilities over network connections for Windows-based applications running on a server.” (MSDN)
Essentially, RDP allows users to control their remote Windows machine as if they were working on it locally (well, almost).
Figure 1: What is RDP?
Communication in RDP is based on multiple channels, and the protocol theoretically supports up to 64,000 unique channels.
The basic functionality of RDP is to transmit a monitor (output device) from the remote server to the client and the keyboard and/or mouse (input devices) from the client to the remote server. The communication during an RDP connection will be extremely asymmetric, while most of the data will go from the server to the client. RDP communication is encrypted with RSA’s RC4 block cipher by default.
Figure 2: Asymmetric communication
Before we get into how an RDP connection actually works, let’s examine the protocols/standards on which RDP relies. The RDP protocol stack looks as follows:
Figure 3: Protocol stack
TPKT is known as the ISO Transport Service on top of TCP. TPKT enables peers to exchange information units that are known as Transport Protocol Data Units (TPDU or PDU).
X.224 is a Connection-Oriented Transport Protocol, it provides a connection-mode transport service. RDP uses it in the initial connection request and response.
T.125 MCS is a Multipoint Communication Service. It allows RDP to communicate through and manage multiple channels.
Sending and receiving data through the RDP stack is essentially the same as the 7 layer OSI model for communication. The data transmitted is sectioned, directed to a channel, encrypted, wrapped, framed and packaged before going over the wire to the other party, then it goes through the same process in reverse.
The implementation of MS RDP has abstracted all of the complexity of the protocol stack, and it allows developers to write extensions to the protocol easily.
In this part, we’ll explain the basics of an RDP connection. Keep in mind that for the sake of simplicity, some details were left out. For more information about the connection (including exact structures, constants, etc.) please see [MS-RDPBCGR].
Figure 4: Connection stages
The RDP connection can be broken down into a few stages:
- Connection Initiation
- Basic Settings Exchange
- Channel Connection
- Security Commencement
- Secure Settings Exchange
- Capabilities Exchange
- Connection Finalization
- Data Exchange
Figure 5: Connection initiation
The RDP connection is initiated by the client using an X.224 Connection request PDU. This packet contains an RDP Negotiation Request that holds a few connection flags and the security protocols supported by the client. Those security protocols can be in one of two categories:
Standard RDP Security
- Default of RSA’s RC4 encryption
Enhanced RDP Security
- CredSSP (TLS + NTLM/Kerberos)
- RDSTLS – RDP enhanced with TLS
More information about RDP Security is available in the next section.
The connection is confirmed by the server using an X.224 Connection Confirm PDU. This packet contains the RDP Negotiation Response which is used to inform the client of the selected security protocol (chosen from the client’s supported protocols) that will be used throughout the entire connection lifetime.
From this point on, subsequent data will be wrapped in an X.224 Data PDU.
Basic Settings Exchange
Figure 6: Basic settings exchange
At this stage, basic settings are exchanged between the client and the server using an MCS Connect Initial PDU and an MCS Connect Response PDU (respectively). These settings (both from the client and the server) include:
- Core Data – RDP Version, Desktop resolution, color depth, keyboard information, hostname, client software information (product ID, build number), etc.
- Security Data – Encryption methods, size of session keys, server random (used later to create session keys) and server’s certificate (some of this is only relevant when using Standard RDP Security).
- Network Data – Information about the requested and allocated virtual channels. This contains the number of channels and an array of specific virtual channels. The client requests the exact type of channels in the request, and the server supplies the actual channel IDs in the response. For more information about those channels see the Channels in RDP section below.
Figure 7: Channel connection
After establishing the list of virtual channels that will be used in the RDP session, here comes the stage at which every individual channel connection is made. This has a few sub-stages:
- MCS Erect Domain Request – Height in the MCS Domain. Since RDP doesn’t take advantage of advanced MCS topologies, it will be 0.
- MCS Attach User Request – request for a User Channel ID
- MCS Attach User Confirm – ID of the User Channel
- (+5) MCS Channel Join Requests and Confirmations – The client will start to request joining the virtual channels by using their IDs. Starting with the User Channel, I/O Channel and continuing with the virtual channels negotiated in the basic settings exchange. The server will, in turn, confirm every successful channel join.
From this point on, subsequent data sent by the client will be wrapped in an MCS Send Data Request PDU, while data sent by the server will be wrapped in an MCS Send Data Indication PDU. Data can now be redirected to virtual channels.
Figure 8: Security commencement
The client sends a Security Exchange PDU containing the client random encrypted with the server’s public key. The client and server then use the random numbers (both from the Basic Settings Exchange’s Security Data and from the Security Exchange PDU) in order to create session encryption keys.
From this point on, subsequent RDP traffic can be encrypted.
Secure Settings Exchange
Figure 9: Secure settings exchange
At this point, the client sends an encrypted Client Info PDU containing information about supported types of compression, user domain, username, password, working directory, etc.
Figure 10: Licensing
This stage is designed to allow authorized users to connect to a terminal server. That is to support more than 2 simultaneous connections (which is the default for “Windows’ RDP Server”) to a server. This requires purchasing a license from Microsoft.
In a lot of cases, no licensing server is configured for the RDP server, in that case, the RDP server will simply send a PDU to the client that “approves” its license (up to 2 sessions only).
You can find more information about the extended licensing phase and the communication between the RDP server and the license server here [MS-RDPELE].
Figure 11: Capabilities exchange
The server sends its supported capabilities in a Demand Active PDU. This PDU contains a structure that has many capabilities of different types. According to Microsoft, we have 28 types of capability sets. Major types are general (OS version, general compression), input (keyboard type and features, fast-path support, etc.), fonts, virtual channels, bitmap codecs and many more. Then, the server may or may not send a Monitor Layout PDU to describe the display monitors on the server. The client will then respond with a Confirm Active PDU containing its own set of capabilities.
Figure 12: Connection finalization
The client and the server exchange a few types of PDUs in order to finalize the connection. All those PDUs originate from the client (PDU can be sent one after the other without waiting for a response). The PDUs are:
- Client/Server Synchronize PDU – Used to synchronize user identifiers between the client the server.
- Client/Server Control PDU (Cooperate) – Both the client and the server send this PDU to indicate shared control over the session.
- Client Control PDU (Request/Grant Control) – Client sends the request for control, server grants it.
- Persistent Key List PDU/PDUs (optional) – The client sends the server a list of keys, each key identifies a cached bitmap. This enables the bitmap cache to be persistent (as opposed to being limited to the lifetime of the connection). Bitmap caching is a mechanism used to reduce network traffic needed to transfer a graphical output from the server to the client.
- Font List/Map PDU – these PDUs were meant to hold information about fonts for the RDP session (font name, average width, signature, etc.), however, it seems like Microsoft is not using it. Having said that, those PDUs are still exchanged between the client and the server at that point, but with no actual data in it (even if there was any data, Microsoft’s documentation specifies you should ignore it).
Figure 13: Data exchange
After the connection has been finalized, the major part of the data sent between the client and the server will be input data (client->server) and graphics data (server->client). Additional data that can be transferred includes connection management information and virtual channel messages.
Basic Input and Output
During the lifetime of the connection, the client and the server exchange basic input/output data. The client is sending the input and the server sends the output.
Input Data – This contains mouse and keyboard information, as well as periodic synchronization (e.g. NAM_LOCK / CAPS_LOCK keys state)
Output Data – The fundamental output data contains bitmap images of the user’s session on the server. In addition, the server can send sound information (only in the form of very basic “beep” – frequency + duration).
This basic input/output data can be transmitted in one of two ways: slow-path or fast-path.
Slow-Path – Normal PDU with all RDP protocol stack headers
Fast-Path – As the name suggests, it was created to reduce both the amount of data transmitted and the amount of processing required to process it. This is done by reducing/removing PDU headers from certain PDU types (e.g. keyboard/mouse input).
Channels in RDP
In RDP, most of the data is being transported through different channels (MCS Layer). There are two main types of channels: Static Virtual Channels and Dynamic Virtual Channels.
Static Virtual Channels (SVC)
SVCs allow communication between different client and server components over the main RDP data connection. There is a maximum of 31 Static Virtual Channels per connection and each channel acts as an independent data stream. Those channels are static because they are requested and created at the Basic Settings Exchange phase during the connection initiation, and they do not change at all during the session.
Not all SVCs are created equal, some are opened by default, and some are negotiated during the Basic Settings Exchange Phase. The SVCs that are being created by default are crucial to the functionality of an RDP connection, while the others enable different extensions for the protocol.
Examples for SVCs created by default:
- I/O Channel
- Message Channel
- User Channel
- Server Channel
Extension SVCs are identified by an 8-byte name, for example:
- rdpdr – Filesystem extension. Allows the redirection of access from the server to the client file system.
- rdpsnd – Sound output extension.
- cliprdr – Clipboard extension. Allows sharing the clipboard between the client and the server.
- drdynvc – Dynamic Virtual Channel Extension (see DVCs below)
All the SVCs channel IDs are supplied during the Basic Settings Exchange phase excluding 2 SVCs: the User Channel which is supplied during the Channel Connection phase in the Attach User Confirm PDU, and the Server Channel which has a fixed value of 0x03EA (1002).
Dynamic Virtual Channels (DVC)
Since the Static Virtual Channels number is limited to 31, RDP also supports Dynamic Virtual Channels. Dynamic Virtual Channels are transported over one specific Static Virtual Channel – DRDYNVC. Those channels are dynamic since you can create and destroy them at any stage of the connection lifetime (after initialization). Developers can create extensions that will transport data over a Dynamic Virtual Channel quite easily. Common uses for DVCs are audio input (client -> server), PnP redirection, graphics rendering, echo channel, video redirection and more.
The following figure describes the relationship between the different types of channels in RDP:
Figure 14: Channels hierarchy
RDP can use compression in output data (both fast-path and slow-path) and in virtual channels. Both the client and the server need to support compression in general, and the specific type of compression negotiated for the connection. The client advertises the compression types it supports in the Client Info PDU during the Secure Settings Exchange.
Every PDU that contains compressed data, needs to have some compression flags (containing the type of compression, etc.) set in the header of that specific PDU.
As mentioned briefly before, the security of the RDP protocol can be one of two types:
Traffic is encrypted using RSA’s RC4 encryption algorithm, using client and server random values that are exchanged during the Basic Settings Exchange phase in the connection initialization.
This type of security enables RDP to outsource all security operations (encryption/decryption, integrity checks, etc.) to an external security protocol. This can be one of the following:
- TLS 1.0/1.1/1.2
Deciding on an enhanced security protocol can be either negotiation-based or direct. The negotiation-based means that the connection initialization (x.224 connection request and response) is outside of the scope of the security protocol. After the initialization, the client and server choose a security protocol, do the external security protocol handshake and from now on all the other stages of the RDP connection will be encapsulated within that external security protocol.
The other option – the direct approach favors security over compatibility. In this approach, the client will start with the external security protocol handshake before sending any RDP related data.
Choosing enhanced security means that the Security Commencement stage will not be executed.
The key benefit of using RDP Enhanced Security is that it enables Network Layer Authentication (details available below).
Network Level Authentication
Network Level Authentication (NLA) refers to the usage of CredSSP to authenticate the user before the initiation of the RDP connection. This allows the server to dedicate resources only to authenticated users.
In case of a critical vulnerability in the RDP protocol, NLA can limit the exploitation of this vulnerability to authenticated users only.
Recent RDP Vulnerabilities
Now that we understand the basics on the RDP protocol, let’s review some of the more recent critical vulnerabilities that were found, and see how they fit into the bigger picture of the RDP protocol.
BlueKeep (CVE-2019-0708) is an RCE vulnerability in Microsoft’s RDP server, affecting Windows machines from Windows 2000 to Windows 7 and Windows Server 2008 R2. It was found and patched in May of 2019. This vulnerability is a use-after-free that was present in the Windows kernel driver that handles RDP connections – termdd.sys.
This vulnerability could be exploited in the connection initialization phase of RDP. As mentioned before, during the Basic Settings Exchange the client and server negotiate which static virtual channels to initialize for the connection and there are channels that will be allocated to the connection regardless of the client’s request, including the MS_T120 channel.
termdd.sys creates a table that contains a pointer to a channel structure for every created channel. This table holds up to 32 (0x20) Channels. The Static Virtual Channel MS_T120 is created by default, and it’s always at index 0x1F. This happens even before the connection sequence begins.
In order to trigger this vulnerability, one needs to create a custom RDP client, that will request for a static virtual channel named MS_T120 in the Basic Settings Exchange. If such channel is requested, the RDP server will then try to find out if this channel has already been created for this connection. If so, it will return the pointer to the existing channel control structure instead of creating a new one. At this point, we’ll have two pointers pointing to one data structure and the connection channels array will look like this:
Figure 15: Structures in memory
To trigger the bug, the RDP client must send a packet that will cause the server to close the MS_T120 channel (legitimate and documented behavior). After closing the channel, the server will go ahead and free the channel control structure of MS_T120, and the pointer to it in the connection channels array, but only the one created due to the client request (not the one created automatically by the server). Now we have a dangling pointer, and the next time the server will try to access the MS_T120 channel (which happens often since this is a crucial channel to the operation of RDP), the system will bug check.
Figure 16: BlueKeep illustration
Since this vulnerability has quite a few write-ups by now, I’ll leave some references for anyone who’s interested in getting all the technical details for triggering and exploiting it.
DejaBlue (CVE-2019-1181 & CVE-2019-1182) is another RCE vulnerability in Microsoft’s RDP server (hence the name) discovered in 2019. This time, the vulnerability affected all versions of Windows (7-10) up until the patch. DejaBlue is an integer overflow vulnerability that was present in a core DLL of the RDP server – RDPCoreTS.dll / RDPBase.dll (depending on the Windows version).
The vulnerability lies in the function that decompresses data sent over a Dynamic Virtual Channel (DVC). Compressed data in a DVC is sent in either a DYNVC_DATA_FIRST_COMPRESSED / DYNVC_DATA_COMPRESSED PDU. The actual data in any of those PDUs is in the form of RDP_SEGMENTED_DATA that can contain multiple segments. A compressed RDP_SEGMENTED_DATA will contain the data uncompressedSize.
When the RDP server receives a compressed DVC PDU, it’ll call a function that will decompress it – DecompressUnchopper::Decompress(). The decompress function will allocate memory for the decompressed data with a size of uncompressedSize + 0x2000, without any checks for the result size. An attacker can make this result integer to wrap around and cause the allocated memory to be smaller than the size of the actual decompressed data. This will effectively lead to a heap overflow, which can be exploited to code execution.
Figure 17: DejaBlue
From the time of writing this post, there is still no PoC/exploit available publicly. Due to the significant risk this vulnerability may pose to the public, we will not share any additional information at this moment. For further reading, here a few public references for in-depth analysis of DejaBlue.
- https://bbs.pediy.com/thread-256766.htm (Chinese)
Securing Your RDP
There are general recommendations to follow that can make the task of attacking your RDP server a lot more difficult for attackers. There are 2 simple actions you can take that will:
- Prevent the exposure of your RDP servers to the internet, keeping them behind your firewall.
- Enable NLA
This can minimize the attack surface by limiting potential attackers only to those who are in your network and have already been authenticated.
Since this was an introductory article on RDP, I tried to distill hundreds of pages worth of RDP documentation into a digestible and fairly short piece of information, so there are many things I didn’t cover here. Our goal was to bring the reader to the point of having a basic understanding of the protocol, as well as the ability to continue reading and researching further about their specific topics of interest.
In the past year, we have seen 2 critical vulnerabilities in this protocol and with over 4.5 million RDP servers exposed to the internet (according to shodan.io) and the risk of having an RDP driven outbreak is very high.
Even though not all RDP servers are Windows servers, we have seen similar vulnerabilities shared between the different implementations of an RDP server, so Windows is not the only potential target. DejaBlue for example, is very similar to CVE-2018-8785 – a vulnerability in FreeRDP (popular open-source RDP server) found by Eyal Itkin about a year before DejaBlue was discovered.
We started this blog by discussing how RDP is a complex protocol with many extensions. Because of its complexity, the potential of finding new critical bugs is still high and we need to be prepared to find and fix those before they could be abused in the wild, or have the ability to respond quickly and minimize the damage of potential future vulnerabilities.