From Public Key to Exploitation: How We Exploited the Authentication in MS-RDP

Posted by Eyal Karni on Mar 13, 2018 10:05:15 AM
Find me on:

 In March Patch Tuesday, Microsoft released a patch for CVE-2018-0886, a critical vulnerability that was discovered by Preempt. This vulnerability can be classified as a logical remote code execution (RCE) vulnerability. It resembles a classic relay attack, but with a nice twist: It is related to RSA cryptography (and prime numbers) which makes it quite unique and interesting.

If you are looking for a general overview of the Vulnerability and Administrative issues, please refer to this blog from Yaron Zinar

The vulnerability consists of a design flaw in CredSSP, which is a Security Support Provider involved in the Microsoft Remote Desktop and Windows Remote Management (Including Powershell sessions). An attacker with complete Man in the Middle (MITM) control over such a session can abuse it to run an arbitrary code on the target server on behalf of the user!

We have demonstrated the attack for Remote Desktop Protocol (RDP) in a domain environment. If the user is a local administrator on the target system, the exploit allows the attacker to run code as SYSTEM, effectively compromising the target server. This is applicable both to Restricted Admin mode and to regular mode of RDP.

There is a video demonstration of the attack here. (It is recommended to read the entire blog first)


Figure 1 - An illustration of CVE-2018-0886 exploit scenario

For the described reasons, and since RDP sessions are very common, this vulnerability could be really valuable to attackers. Further, because it is by design, the vulnerability resides in all windows versions (from Vista),  as long as fix is not applied. Fix can be found here

In this blog, we will go through the journey I went in facilitating the exploit. Along the way, I will explain the technical and mathematical details of the vulnerability.  

It is assumed that the reader has some familiarity with the Active Directory (AD) environment, mainly with Kerberos, NT LAN Manager (NTLM), MS-RDP and Security Support Provider Interface (SSPI). 

The Journey: How we found the vulnerability

Issue #1

Our journey begins with another vulnerability that we discovered at Preempt. In the context of that vulnerability we demonstrated the ability to do NTLM relay in the case of RDP Restricted Admin mode even without knowledge of the private key of the destination server. This is not trivial since the entire process is done under Transport Layer Security (TLS), and is thus encrypted by the certificate of the server. You can learn more about this vulnerability here.

Exploiting the NTLM relay vulnerability was possible because of the way RDP is implemented. Let's take a look at the process:

  1. Negotiation over capabilities (Usually CredSSP is chosen)
  2. TLS is established
  3. Network Layer Authentication (NLA) is carried out using CredSSP
  4. The client verifies the certificate, displaying warning if needed
  5. The user accepts the warning
  6. The user sends its password over CredSSP (In Regular Mode)
  7. Login and remote UI activities

After establishing the encrypted secure session, the next step in RDP is NLA. The server validates that the client possesses the credentials for the user by the usual method of authentication (e.g., Kerberos). This saves the need to allocate resources needed for logon.

In step 4, the client checks the certificate. A warning won’t be shown if the certificate is signed by a trusted Certificate Authority (CA) or if the certificate is trusted manually. However, Microsoft decided the server is also considered validated if Kerberos authentication is performed. The certificate is coupled with the Kerberos Identity in step 3.

If neither condition is met, the following warning will be shown:


Figure 2 - A standard MS-RDP warning

You can see that NLA happens before validating the certificate. Thus, step 3 can be made with any forged certificate. Assuming everything else is done securely and correctly, this won’t be an issue, but this is not the case here. We will call this issue #1.

Moving Toward Issue #2

Also when dealing with issues, sometimes it takes two to tango. I found a second issue when I looked at the specification of CredSSP.

CredSSP is the underlying protocol that is used to relay the credentials of the user in MS-RDP. Basically, this protocol is very simple: TSRequest messages are transferred from the client to the server and vice versa. These messages carry SPNEGO tokens used for the negotiation phase of the authentication protocol. The negotiation is transparent for the CredSSP client/ server. The protocol is carried over the secured TLS session established in step 1.

Let’s take a look at the chart:


Figure 3 - CredSSP NLA Part

In the final negotiation message (accept_complete), the client computer transfers the NLTM/Kerberos final token, but it also sends the public key of the server encrypted and signed with SSPI. The public key structure is derived from the key parameters of the RSA. What is important for now, is that it contains the N,e parameters that are the essence of the server certificate.

This is a common variant of a technique called Channel Binding which is aimed at thwarting credential relay attacks by binding the TLS session with the Windows authentication. So, the identity of the server (as represented by the certificate) is coupled with the standard Windows Authentication identity (as represented by the relevant account secret).

Still, this design carries a fatal flaw inherent in it. In this stage, you might want to take a few minutes to spot it yourself.

Issue #2

The second issue is that the client trusts the public key of the server. It actually encrypts and signs bytes of the server (the public key structure) without first validating its identity. We can see the attack as a private case of a Chosen Plaintext Attack (CPA). In this case, it encrypts and signs it the same way it does for an application in SSPI (compared to a classical attack which only encrypts).  

This is the essence of the vulnerability. To exploit it, an attacker would set up a rogue server, and use the public key both as application data and as a valid RSA key. Then it would forward the encrypted and signed application data to the real intended server (no other server is possible in the current exploit).


Figure 4 - A diagram of the exploit

But is it really possible? After all, the public key is dual purposed. It should be valid as both an RSA key and as a signed application data of a yet-to-be-determined windows protocol. This protocol should support SSPI of course, but all the standard windows protocols do support it.

Let us focus our attention first on what seems to be the toughest problem: we need control over the RSA public key (which is translated to Application Data).


Broken RSA

(Some familiarity with the mathematics behind RSA is assumed. )

We can see that if we implement the usual RSA authentication, we have little control over N (at least), as it is chosen as the multiplication of two (random) primes. For this reason, we have chosen to implement our own “broken” version of RSA.

We choose \(N = p\) where p is prime.

Then we know that \(\varphi(N) = p-1 \) (you can see that any number smaller than p is co-prime to p).

We have the same e smaller than N as part of the public key, e is coprime to \(\varphi(N)\)  and also \(c = m^e\mod N\)  .

This allows us to create an “encryption” that works (Although it is trivially breakable).

Given a message (which is encoded in a way such that it in this group) m,  \(c = m^e\mod N\) is the “cipher text”.  It is trivially broken because anyone who knows N can find d such that \(ed + \phi(N)C=1 \) using the egcd algorithm. But luckily, privacy is not considered an issue in an exploit. :)  

So, for the “broken” RSA to work, we have almost nothing to change. Encryption and decryption work in the same way as in RSA. We can use the original OpenSSL lib for it, but we still need to remove some optimizations done in the server, as there are no two primes involved.

After completing this step, we have a working encryption, and control over N.

But how much control do we really have? Can we find primes easily?  

Actually, yes!

Finding Primes

According to the Prime Number Theorem:

$$\frac{x}{\ln x}<\pi(x)<1.256\frac{x}{\ln x}$$

Where \(\pi\) is the prime counting function (how many prime numbers are there that are less than x) .

We have that the chance of randomly falling on an prime when choosing a random number k in the range 1...N is:

$$P(\text{k is a prime}) = \frac{\pi(N)}{N}$$

$$\frac{1}{\ln N} < P(\text{k is a prime}) < 1.256 \ln N$$

Where N is a number that is around 600 bytes or in the vicinity of \(2^{600 \cdot 8}\) (this is a realistic scenario), we get that the probability that a random number would be a prime is between \(\frac{1}{3328} \) and \(\frac{1}{2651} \). Doing the exact calculation for the appropriate range, yields a similar result.

A freedom of 2 bytes should be enough to find a suitable prime because \(\log_{256} \ln N \approx 1.46\). We need to try just around ~1650 numbers in order to find a suitable prime (we can pass over the odd numbers). On my computer,  it takes an average of 70 seconds to do so (and it is a one-time process for each environment to exploit).

So, this problem is solved. But we still need to find a suitable protocol.

Protocol requirements

The most obvious requirement is that the Public Key Structure will be coded as the Application Data. This structure is ASN.1.


Figure 5 -  Public Key Structure

What it means for us is that the first 8 bytes of the data are not under our (full) control.

NTLM or Kerberos

A question to consider is whether we can implement NTLM or Kerberos. SSPI has standard mechanisms for signing based on NTLM and Kerberos authentication. In both cases a header that contains the checksum and sequence number is added to the Application Data, if signing was agreed in the negotiation. In addition, the SPNEGO negotiation ends with signing and encryption enabled, and the the sequence number in the case of Public Key Structure will be 0.

However, there is an important difference between NTLM and Kerberos handling . It is demonstrated in the following diagram (for RPC as an important example) :


Figure 6 - NTLM vs Kerberos in GSSAPI

The Public Key Structure is actually encoded as “headerless protocol”. The entire structure is encrypted and signed in NTLM case, but the RPC server expects only the Application Data to be encrypted.  So, NTLM adds another restriction for the protocol. This restriction actually prevented us from implementing the attack for NTLM because we couldn’t find a suitable “headerless” protocol. We aren’t sure that it is impossible. Finding such protocol would likely produce a stronger exploit, allowing the attacker to choose a different server to target using NTLM Relay.

Another point to note is that in Kerberos, ticket service name is not strictly forced, as long as the account matches. The account in RDP is the machine account. So, we can say that Kerberos is mildly vulnerable to Kerberos Relay. A data signed for use in one application can be used in another one, given a similar CPA.

Here is a summary of the requirements for the protocol:

  • Supports SPNEGO
  • Encoding requirements
    • Application Data is Non-ASN.1
    • Specific 8-bytes Prefix which we have no control over
    • Includes some degree of freedom
    • No Header if dealing with NTLM
  • Able to do harm with a single signed packet
  • Available on wide variety of machines

One protocol that satisfies all of the requirements is MSRPC (Besides the extra requirement required for NTLM to work). We are not aware of any other protocol that meets these requirements.


The coding of MSRPC Application Data is MIDL. This is quite an messy and very diverse structure that basically describes the arguments passed to the remote procedure.

For the 8 uncontrolled bytes in the beginning we can choose any function where its first argument is string(maybe pointer in general). This is because an 8-bytes field (in the case of 64-bit implementation) called ReferentId is present, where the destination server is indifferent to its value.

As for the freedom bytes, it wouldn’t have been much of a problem anyway, but RPC ignores excessive bytes, so it is easiest to put them all at the end.

The exploit uses the following function (Opnum 1) of the Task Scheduler Interface:


Figure 7 - The exported function

The Task Scheduler Interface is the modern interface for managing scheduled tasks in windows. It is similar to the ATSvc interface (triggered by the AT command), but is more powerful, as it provides more control over the created task and its properties.

This is an example for the command that is coded in the exploit:

Screen Shot 2018-03-12 at 1.17.19 PM.png

This command creates a task with user id of SYSTEM. The executable is found in a share controlled by the attacker, and it is run immediately. Therefore, it could be any stale code. So, there is no need to do privilege escalation if the user is already an Administrator.

Real World Obstacles

Finally, we consider some real world obstacles. While doing MITM, in many cases, is not that difficult for an attacker (for example through ARP Poisoning), the real obstacle here is Windows Firewall. If it is ON, then on a regular modern OS, incoming RPC is not enabled by default for any interface.

Despite this, the vulnerability and threat is still very much real, and applying the patch is important. Because of the following reasons:

  1. Domain Controllers are still vulnerable to this attack by default.
    This is because a rule concerning RPC exists in Domain Controllers that enables any svchosts.exe DCOM interfaces. Furthermore, a quick survey found that RDP is the most common way in which domain admins tends to access the DC. In other words, by exploiting this attack, an attacker is likely to gain a full control over the domain
  2. Many times, Windows Firewall is turned OFF or RPC is enabled extensively (It is recommended to enable it selectively for the services you need)
  3. It could be exploited in various ways, bypassing different possible defences in various environments. Not only using different interfaces of MSRPC, but also exploiting different protocols. (If you manage to, we would like to know)

In the scenario described in the beginning, the remote desktop session would fail with the following message after a few seconds:


Figure 8 - Error message displayed after RDP connection fails due to exploit

And a malicious payload would run silently on the server in a privileged context. Other than this, no warning or suspicious indication will be present.


In this blog post, we have laid down the details for an attack on MS-RDP with the Task Scheduler Interface as the destination. This attack has nearly 100% success given a server with RPC enabled. And assuming an attacker is capable of doing MITM.  

Hopefully you found this vulnerability interesting. Apparently, strong protocol-based logical vulnerabilities haven’t passed from the world. I think this vulnerability stresses the importance of identity validation as soon as possible and strictly before signing any data. The issue brought here of public key signing might be something to look for in general.

You can see the video demo of the attack here

The author wishes to thank Yaron Zinar, Preempt Research Team Lead, for the support and guidance along the way, as well as on help in writing this blog post. And also to Heather Howland, VP Marketing, and to Wade Williamson, Product Marketing for all the assistance regarding this blog.

We will be releasing the tools used for the exploit after we present at Black Hat Asia later this month.

Hope you enjoyed reading this blog.


Topics: Multi-factor Authentication, kerberos, Hacking, Black Hat, Security Advisory, Microsoft, RDP