This post seeks to demonstrate why users learning to ignore those certificate warnings for SSL-based RDP connection could leave them open to “Man-In-The-Middle” attacks. The MiTM attack demonstrated displays keystrokes sent during an RDP session. We conclude with some advice on how to avoid being the victim of such an attack.

Types of RDP connections

Before we start, let’s first clarify which of the various RDP connection types this post is about. There are 3 types of connection:

  • RDP Security Layer
  • SSL (TLS 1.0)
  • CredSSP (SSL with NLA)

It’s the middle one we’ll demonstrate an attack on in this post. On the Terminal Server, SSL is configured like this (with any NLA checkboxes unticked):

RDP configuration used

RDP configuration used

2003-rdp-setting-not-vulnerable
image-1511

RDP configuration used

Some connections may also be vulnerable if the server is set to “Negotiate” its Security Layer to – as that could result in SSL being used.

SSL certificate warning

If users are used to dismissing a warnings like this one each time they connect, then this post is relevant to them:

ssl-warning
image-1512

SSL warning that should not be routinely ignored

Attack overview

At a high level, the attack will proceed in a similar way to any SSL MiTM attack:

  1. Have the victim connect to a PoC tool (rdp-ssl-mitm.py) on our system instead of the RDP server they’re trying to reach
  2. Using the RDP protocol, our tool will negotiate the use of SSL
  3. At the point the connection is upgraded to SSL, our tool will negotiate an SSL connection with the RDP client using its own (untrusted) SSL certificate. This will give our tool access to data sent by the RDP client in cleartext
  4. Our tool also needs to create an SSL connection with the legitimate RDP server down which it will send data from the RDP client

The only complication to this attack is that our tool has to talk the RDP protocol briefly before creating the required SSL connections.

1. Having the victim connect to us

In a real attack, we’d need to have the RDP client connect to our system instead of the target server. This could be achieved using ARP spoofing, DNS spoofing or some other method. Rather than cloud the demonstration with such details, we’ll assume this is step is possible and just type the IP address of the attacker system into the victim RDP client.

On our attacker system (192.168.190.170), we start our PoC tool. We tell it forward connections to the legitimate RDP server 192.168.2.96:

$ ./rdp-ssl-mitm.py -r 192.168.2.96:3389
[+] Listening for connections on 0.0.0.0:3389

And we simply enter the IP address of the attacker system into the RDP client (the client connects from 192.168.190.1):

rdp-attack-prior-to-logon
image-1513

We enter the attacker IP address to avoid the complexity of ARP spoofing

2. Talk RDP to the client to negotiate the use of SSL

The negotiation of SSL is quite short within the RDP protocol:

Message #1: Client > MiTM > Server

03 00 00 13 0e e0 00 00 00 00 00 01 00 08 00 *03*
00 00 00

This message is fairly static and our tool just passes it through to the server unaltered. The *03* means that the client supports RDP Security Layer, SSL and CredSSP.

Message #2: Server > MiTM > Client

03 00 00 13 0e d0 00 00 12 34 00 02 00 08 00 *01*
00 00 00

In the next message the server chooses the protocol to use. The *01* in this case means the the server has chosen SSL (not CredSSP which would be *02*). Again, we pass this message back to the client unaltered.

Note that if the server were to select CredSSP (*02*), then the demonstration would fail. We’re attacking SSL, not CredSSP.

3. Create SSL connection with RDP client

Message #3: Client > MiTM

The 3rd message is the start of an SSL connection. Here is the SSL Client Hello message beginning *16 03 01*… (03 01 being the version of SSL used: SSL 3.1 AKA TLS 1.0).

*16 03 01* 00 5a 01 00 00 56 03 01 52 21 ac be 63
20 ce de 4b a5 90 18 f0 66 97 ee 9d 54 14 e3 1c
... snip ...

Our tool does not forward this data directly to the server. Instead it responds with a “SSL Server Hello” message and proceeds to complete the SSL connection with the client.

The SSL certificate we present to the RDP client is issued to fred and this is displayed in the mstsc SSL warning shown to the user:

fred
image-1514

The certificate presented by our PoC tool causes this security warning

The details of the SSL certificate differ to those the user would normally see – if the user were to check. To refine the attack we could make the certificate details match more closely, but we’d never get the signature to be the same as the normal certificate, so there’d always be a difference.

4. Create SSL connection with RDP server

Simultaneously, our tool also sends and SSL Client Hello to the RDP server and creates a second SSL connection.

Displaying key strokes

Our tool is now in a position to display the cleartext messages about keystrokes (for example) sent by the RDP client. It is relatively easy to determine what sort of message is sent when a key is pressed. The following two 4-byte messages are sent when the ‘p’ key is pressed:

44 04 00 19
44 04 01 19

The 3rd byte is the direction of key (00 means key-down, 01 means key-up).  The 4th byte is the key scan code.  If we look up 0×19 we find it corresponds to the p key.

In the general case, the scan-code to character mapping depends which keyboard you’re using. In the PoC tool I implemented the mapping for for QWERTY keyboards, so if you have a UK/US keyboard, it should translate the majority of scan-codes to the correct characters. Note that we don’t get know whether characters are uppercase or lowercase. We’d have to manually track the status of CAPS Lock and SHIFT keys.

Without getting too bogged down in the details, here’s some sample output from the PoC tool that shows keystrokes being logged – in particular an administrator logging in with username Administrator, password Password:

$ ./rdp-ssl-mitm.py -r 192.168.2.96:3389 
[+] Listening for connections on 0.0.0.0:3389
[+] Incoming connection from 192.168.190.1:60370
[+] New outgoing request to 192.168.2.96:3389 (SSL: 0)
[+] Connected
[+] Detected incoming SSL connection. Turning self into SSL socket
[+] Incoming connection from 192.168.190.1:60374
[+] New outgoing request to 192.168.2.96:3389 (SSL: 0)
[+] Connected
[+] Detected incoming SSL connection. Turning self into SSL socket
<LShift-down>A<LShift-up>DMINISTRATOR<Tab><LShift-down>P<LShift-up>ASSWORD<Enter>

Conclusions

Learning to ignore SSL certificate warnings is as bad for RDP connection as it is for HTTPS websites. The results are similar: users quickly become vulnerable to “Man-In-The-Middle” attacks. Such attacks can harvest usernames, passwords, keystrokes and other sensitive data.

Using SSL certificates that are signed by a Certificate Authority the RDP client trusts will result in no warning under normal operation, so is highly recommended.

This attack doesn’t work if the server mandates NLA, so using NLA is also highly recommended.

It’s important to note that this isn’t a vulnerability in the RDP Client or Server software. Nor is this a  new discovery. It’s a weakness in way RDP is sometimes used which stems from users ignoring security warnings. At a technical level, this is a fairly vanilla SSL MiTM attack.

It might be interesting to extend this work by recording screen captures; or by injecting images of login boxes to encourage users to part of with other credentials. There would also be an opportunity to attack any drives that the RDP client has mapped for drive redirection – see Attacking the RDP Clients for inspiration. These would be pretty demanding coding challenges, though!


Request to be added to the Portcullis Labs newsletter

We will email you whenever a new tool, or post is added to the site.

Your Name (required)

Your Email (required)