Corelight Bright Ideas Blog: NDR & Threat Hunting Blog

How to Mitigate RDS/RDP Vulnerabilities Using Corelight & Zeek | Corelight

Written by Richard Bejtlich | May 23, 2019 4:00:00 AM

Introduction

On May 14 Microsoft released patches for, and details about, a remote code execution vulnerability in Remote Desktop Services (RDS), the graphical interactive desktop offered with most Windows operating system platforms. This vulnerability bears the Common Vulnerabilities and exposures number CVE-2019-0708. Remote Desktop Protocol (RDP) is the method by which clients can interact with Windows platforms offering Remote Desktop Services. Because the vulnerability is exercisable prior to authentication, any vulnerable system offering RDS could be exploited.

Putting on my former CSO hat, there are several questions I would ask regarding this vulnerability in my enterprise:

  1. Do any of our organization’s services rely on RDS?
  2. If we rely on RDS, which systems offer RDS?
  3. Of the systems which offer RDS, which are exposed to attackers?
  4. Of the systems exposed to attackers, which are vulnerable?
  5. Of the systems which are vulnerable, which may have been exploited?
  6. Of the systems which may have been exploited, when did exploitation occur?

These questions try to place the technical reality in line with the business aspects of the situation in hand. It may be the case that several systems expose vulnerable RDS implementations to intruders, and those systems have indeed been exploited. However, they may be on systems that have zero bearing on business continuity and offer no access to relevant business functions. For example, they might be legacy systems in a business unit that is about to be decommissioned. Of course, it is poor practice to provide easy access to such systems, as they will be exploited for use as stepping stones and related adversary infrastructure to attack other targets. Nevertheless, CSOs with limited time and resources must make prioritization decisions on a daily basis.

With these caveats in mind, let’s assume the answer to question one is “yes.” We can use Zeek data collected by Corelight sensors to try to answer each of the remaining five questions. Beyond these questions we would consider issues of proceeding with incident response, but that is out of scope for this particular article.

Question 2: Which systems offer RDS, Part 1

There are two ways to discover RDS servers in the enterprise. The first method is to search for traffic to port 3389 TCP, the standard RDS port, registered with IANA (along with port 3389 UDP) as MS WBT Server (for Microsoft Windows Based Terminal Server), and to assume that traffic is indeed RDP speaking to a RDS server.

Corelight’s conn.log is a simple yet easy way to discover this traffic. For example, the following shows a conversation between two Windows 10 systems, with one acting as a RDS server and one acting as a RDS client.

{“ts”:1558454943.683482,”uid”:”CLN4yy3UzLYgHxCaMj“, “id.orig_h”:”192.168.4.99″,”id.orig_p”:51583,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389, “proto”:”tcp“,”service”:”ssl“,”duration”:8.821903,”orig_bytes”:1138,”resp_bytes”:1660, “conn_state”:”RSTO”,”missed_bytes”:0,”history”:”ShADdR”,”orig_pkts”:9,”orig_ip_bytes”:1510,”resp_pkts”:6, “resp_ip_bytes”:1912}

{“ts”:1558454959.137565,”uid”:”CASytj4BfcgX536Bu2“,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:51584,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389,”proto”:”tcp“,”service”:”ssl“,

”duration”:21.809092,”orig_bytes”:21915,”resp_bytes”:11699,”conn_state”:”RSTO”,

”missed_bytes”:0,”history”:”ShADdaR”,”orig_pkts”:421,”orig_ip_bytes”:38767,

”resp_pkts”:277,”resp_ip_bytes”:22791}

{“ts”:1558454959.286499,”uid”:”COEtNr8tEtMcdlL62″,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:56264,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389,”proto“:”udp“,

”duration”:18.228085,”orig_bytes”:323451,”resp_bytes”:571812,”conn_state”:

”SF”,”missed_bytes”:0,”history”:”Dd”,”orig_pkts”:524,”orig_ip_bytes”:338123,

”resp_pkts”:752,”resp_ip_bytes”:592868}

I generated these three log entries in a single RDS session. The client and server had one conversation using three separate sessions. Curiously, the third session was held over port 3389 UDP. This is a feature of newer RDS implementations. I’ve also highlighted the UID of the first two sessions, as we will see them in later log entries.

The first method assumed ports 3389 TCP and UDP were really RDS sessions, but we see Corelight report “ssl” as the service for the first two, and no service for the last session. We can check Corelight’s rdp.log for more information.

{“ts”:1558454943.689058,”uid”:”CLN4yy3UzLYgHxCaMj“,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:51583,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389,

”cookie”:”DESKTOP-C”,”result”:”encrypted”,”security_protocol”:”HYBRID_EX”,”cert_count”:0}

{“ts”:1558454959.145612,”uid”:”CASytj4BfcgX536Bu2“,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:51584,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389,

”cookie”:”DESKTOP-C”,”result”:”encrypted”,”security_protocol”:”HYBRID_EX”,”cert_count”:0}

These two log entries confirm that Corelight tracked two of the sessions as RDP and saw the RDP cookie DESKTOP-C in the clear before the session became encrypted. Remember that we can track these sessions using the highlighted UIDs, a factor that makes searching large data stores much easier.

Profiling RDS

Before answering the other questions, let’s take a slight detour to learn a bit more about the RDP session observed in this example. Corelight also generated two ssl.log entries, as the conversations between the RDS server and client were encrypted with TLS.

{“ts”:1558454952.457575,”uid”:”CLN4yy3UzLYgHxCaMj“,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:51583,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389,”version”:

TLSv12“,”cipher“:”TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384″,”curve”:

”secp384r1″,”server_name”:”192.168.4.50″,”resumed”:false,”established”:true,”cert_chain_fuids”:

[“Fkb2FiGfPy5Kwp4j1″],”client_cert_chain_fuids”:[],”subject”:”CN=LAPTOP-EX“,

”issuer”:”CN=LAPTOP-EX“}

{“ts”:1558454959.166002,”uid”:”CASytj4BfcgX536Bu2“,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:51584,”id.resp_h”:”192.168.4.50″,”id.resp_p”:3389,”version”:

TLSv12“,”cipher“:”TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384″,

”curve”:”secp384r1″,”server_name”:”192.168.4.50″,”resumed”:false,

”established”:true,”cert_chain_fuids”:[“FML2hm1rBEGNXhalda”],

”client_cert_chain_fuids”:[],”subject”:”CN=LAPTOP-EX“,”issuer”:”CN=LAPTOP-EX“}

Looking at the ssl.log entries we see the TLS version (1.2) and the identities of the subject and issuer in the server certificates. We also see the ciphers, but those of you familiar with JA3 and JA3s hashes may miss seeing those values here. In the next (brief) section I will include a few examples with JA3 and JA3s.

The x509.log file provides additional detail on the certificates provided by the RDS server.

{“ts”:1558454952.457575,”id”:”Fkb2FiGfPy5Kwp4j1″,”certificate.version”:3,

”certificate.serial”:”20E61515393221B844AB2AFEDC55C221″,

”certificate.subject”:”CN=LAPTOP-EX”,”certificate.issuer”:

”CN=LAPTOP-EX”,”certificate.not_valid_before”:1547320303.0,”certificate.not_valid_after

”:1563131503.0,”certificate.key_alg”:”rsaEncryption”,”certificate.sig_alg”:”sha256WithRSAEncryption”,

”certificate.key_type”:”rsa”,”certificate.key_length”:2048,”certificate.exponent”:”65537″}

{“ts”:1558454959.166002,”id”:”FML2hm1rBEGNXhalda”,”certificate.version”:3,

”certificate.serial”:”20E61515393221B844AB2AFEDC55C221″,”certificate.subject”:

”CN=LAPTOP-EX”,”certificate.issuer”:

”CN=LAPTOP-EX”,”certificate.not_valid_before”:1547320303.0,”certificate.not_valid_after”:1563131503.0,

”certificate.key_alg”:”rsaEncryption”,”certificate.sig_alg”:”sha256WithRSAEncryption”,

”certificate.key_type”:”rsa”,”certificate.key_length”:2048,”certificate.exponent”:”65537″}

Finally, Corelight generated files.log entries for the x509 certificates.

{“ts”:1558454952.457575,”fuid”:”Fkb2FiGfPy5Kwp4j1″,

”tx_hosts”:[“192.168.4.50″],”rx_hosts”:[“192.168.4.99″],”conn_uids”:[“CLN4yy3UzLYgHxCaMj”],”source”:”SSL”,

”depth”:0,”analyzers”:[“SHA1″,”MD5″,”X509″],

”mime_type”:”application/x-x509-user-cert”,”duration”:0.0,”is_orig”:false,”seen_bytes”:742,”missing_bytes”:0,

”overflow_bytes”:0,”timedout”:false,”md5″:”239df883c369c6e36a16e8094790d1a2″,

”sha1″:”db082a0eb02273d3bfde785fd0ed738ae6e9889b”}

{“ts”:1558454959.166002,”fuid”:”FML2hm1rBEGNXhalda”,

”tx_hosts”:[“192.168.4.50″],”rx_hosts”:[“192.168.4.99″],

”conn_uids”:[“CASytj4BfcgX536Bu2″],”source”:”SSL”,

”depth”:0,”analyzers”:[“SHA1″,”MD5″,”X509″],

”mime_type”:”application/x-x509-user-cert”,”duration”:0.0,”is_orig”:false,”seen_bytes”:742,

”missing_bytes”:0,”overflow_bytes”:0,”timedout”:false,”md5″:

”239df883c369c6e36a16e8094790d1a2″,”sha1″:”db082a0eb02273d3bfde785fd0ed738ae6e9889b”}

JA3 and JA3s

In the last section I mentioned that the ssl.log entries did not include JA3 and JA3s hashes. Zeek creates these when it sees TLS sessions, profiling the server and client cipher suites. In my testing, I was able to collect these hashes for a few RDP connections. For example:

{“ts”:”2019-05-21T14:31:23.652821Z”,”uid”:”CYJwaj2AJUF65jzXn4″,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:49697,”id.resp_h”:”10.2.3.4″,”id.resp_p”:3389,

”version”:”TLSv10“,”cipher”:”TLS_RSA_WITH_AES_128_CBC_SHA”,

”server_name”:”10.2.3.4″,”resumed”:false,”established”:true,

”cert_chain_fuids”:[“FsDhX9Fmres3r1pN6″],”client_cert_chain_fuids”:[],”subject”:

”CN=WIN-S”,”issuer”:”CN=WIN-S”,”validation_status”:

”unable to get local issuer certificate”,”ja3“:”ce5f3254611a8c095a3d821d44539877″,

ja3s“:”4192c0a946c5bd9b544b4656d9f624a4”}

{“ts”:”2019-05-21T14:29:12.226314Z”,”uid”:”C99iJU3uNH7ThlePai”,

”id.orig_h”:”192.168.4.99″,”id.orig_p”:49689,”id.resp_h”:”14.2.3.4″,

”id.resp_p”:3389,”version”:”TLSv12“,”cipher”:”TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384″,

”curve”:”secp256r1″,”server_name”:”14.2.3.4″,”resumed”:false,

”established”:true,”cert_chain_fuids”:[“Fb70Je16HU3xa6rSV3″],

”client_cert_chain_fuids”:[],”subject”:”CN=98″,”issuer”:”CN=98″,

”validation_status”:”unable to get local issuer

certificate”,”ja3“:”ce5f3254611a8c095a3d821d44539877″,

ja3s“:”649d6810e8392f63dc311eecb6b7098b”}

During the course of testing I did not determine why Zeek created JA3 and JA3s hashes for some sessions but not others. This is an open area for investigation!

RDS on Older Systems

Before turning to the second part of the second question, let’s take a quick look at how RDS sessions with older systems appear. The examples thus far have shown RDP between two modern Windows 10 systems. Older systems may reveal more information.

For example, here is a RDS session between a Windows 10 client and a Windows XP server as shown in the rdp.log:

{“ts”:”2019-05-21T14:51:14.442010Z”,”uid”:”CoTtNI3yXDM5SgysSh”,”id.orig_h”:

”192.168.4.99″,”id.orig_p”:51545,”id.resp_h”:”1.2.3.4″,”id.resp_p”:3389,

”cookie”:”DESKTOP-C”,”cert_count”:0}

{“ts”:”2019-05-21T14:51:17.398360Z”,”uid”:”C9AWBr4mBjFXelWM61″,”id.orig_h”:

”192.168.4.99″,”id.orig_p”:51546,”id.resp_h”:”1.2.3.4″,

”id.resp_p”:3389,”cookie”:”DESKTOP-C”,”result”:”Success”,”security_protocol”:”RDP”,

”keyboard_layout”:”English – United States”,

”client_build”:”client_build-17763″,”client_name”:”DESKTOP”,

”client_dig_product_id”:”07be6c31-6771-4bfd-a0d5-6e0d44a”,”desktop_width”:1024,”desktop_height”:768,

”requested_color_depth”:”32bit”,”cert_type”:”RSA”,”cert_count”:1,

”cert_permanent”:true,”encryption_level”:”Client compatible”,”encryption_method”:”128bit”}

In the following example, the RDS server is running Windows Server 2003:

{“ts”:”2019-05-21T14:39:52.926284Z”,”uid”:”CHygiPXs5RE2ie9T8″,”id.orig_h”:”192.168.4.99″,”id.orig_p”:49924,

”id.resp_h”:”1.2.3.5″,”id.resp_p”:3389,

”cookie”:”DESKTOP-C”,”result”:”SSL_NOT_ALLOWED_BY_SERVER“,”cert_count”:0}

{“ts”:”2019-05-21T14:39:54.736802Z”,”uid”:”CM28pz2WCTikYpPSPe”,”id.orig_h”:”192.168.4.99″,

”id.orig_p”:49925,”id.resp_h”:”1.2.3.5″,”id.resp_p”:3389,

”cookie”:”DESKTOP-C”,”result”:”Success”,”security_protocol”:”RDP”,”keyboard_layout”:

”English – United States”,”client_build”:”client_build-17763″,”client_name”:”DESKTOP”,”client_dig_product_id”:

”07be6c31-6771-4bfd-a0d5-6e0d44a”,”desktop_width”:1024,”desktop_height”:768,”requested_color_depth”:

”32bit”,”cert_type”:”RSA”,”cert_count”:1,”cert_permanent”:true,”encryption_level”:

”Client compatible”,”encryption_method”:”128bit”}

These log entries really only differ due to the highlighted SSL_NOT_ALLOWED_BY_SERVER message in the rdp.log entry for the Windows Server 2003 system.

With this in mind, let’s turn to the second part of the second question.

Question 2: Which systems offer RDS, Part 2

In the first part to the answer to question 2, I noted that the first way to find RDS servers was to search for traffic to port 3389 TCP, the standard RDS port. What happens if RDS is listening on a non-standard port?

Thanks to Corelight’s dynamic protocol detection, we can look directly at the rdp.log to find RDP sessions that involve nonstandard ports. (We could look at the conn.log as well, but we would not know what to look for until we discover the nonstandard port.)

Consider this entry in rdp.log:

“ts”:1558360661.755249,”uid”:”Cd3R6i1uAyfmOklWLa“,”id.orig_h”:”192.168.4.42″,

”id.orig_p”:49849,”id.resp_h”:”192.168.4.50″,”id.resp_p”:10000,”cookie”:”root”,

”result”:”encrypted”,”security_protocol”:”HYBRID_EX”,”cert_count”:0}

Here we see a RDS server listening on port 10,000 TCP.

Searching for the highlighted UID we find the corresponding conn.log entry:

“ts”:1558360661.735693,”uid”:”Cd3R6i1uAyfmOklWLa“,”id.orig_h”:”192.168.4.42″,

”id.orig_p”:49849,”id.resp_h”:”192.168.4.50″,”id.resp_p”:10000,”proto”:”tcp”,

”service”:”ssl”,”duration”:18.047717,”orig_bytes”:23723,”resp_bytes”:13207,”conn_state”:”RSTO”,

”missed_bytes”:0,”history”:”ShADdaR”,”orig_pkts”:504,”orig_ip_bytes”:43895,”resp_pkts”:330,

”resp_ip_bytes”:26419}

Now that we know RDS is available on port 10,000, we can look at the conn.log for other entries:

“ts”:1558360656.178328,”uid”:”CJA1pH2YsGdmlAKUN3“,”id.orig_h”:”192.168.4.42″,

”id.orig_p”:49838,”id.resp_h”:”192.168.4.50″,”id.resp_p”:10000,”proto”:”tcp”,

”duration”:5.550125,”orig_bytes”:1242,”resp_bytes”:2333,”conn_state”:”RSTO”,”missed_bytes”:0,

”history”:”ShADadR”,”orig_pkts”:10,”orig_ip_bytes”:1654,”resp_pkts”:8,”resp_ip_bytes”:2665}

“ts”:1558360661.735693,”uid”:”Cd3R6i1uAyfmOklWLa“,”id.orig_h”:”192.168.4.42″,

”id.orig_p”:49849,”id.resp_h”:”192.168.4.50″,”id.resp_p”:10000,”proto”:”tcp”,”service”:”ssl”,

”duration”:18.047717,”orig_bytes”:23723,”resp_bytes”:13207,”conn_state”:”RSTO”,

”missed_bytes”:0,”history”:”ShADdaR”,”orig_pkts”:504,”orig_ip_bytes”:43895,

”resp_pkts”:330,”resp_ip_bytes”:26419}

While the second entry is familiar, we also see a new first entry. This is another conversation within the same RDP session, similar to what we saw earlier on port 3389 TCP. Note there are no entries for port 10,000 UDP in this log.

Answering Questions 3-6

With this understanding of the data about RDS provided by Corelight, we can consider the final four questions. They involved determining which systems are exposed to attackers, which are vulnerable, which may have been exploited, when did exploitation occur, and how to proceed with incident response.

Finding RDS exposed to intruders requires instrumenting the enterprise such that Corelight sensors have visibility to inbound Internet traffic. Zeek and Corelight are not able to directly answer questions of vulnerability, as Windows does not disclose server patch levels via RDP.

Comparing the way older Windows systems, such as Windows XP and Windows Server 2003, offer RDS services, it appears that by default they do not provide TLS encryption for RDP sessions. As pointed out in this McAfee blog post, and verified by looking at traces involving older Windows systems, the portion of the RDP session that is likely to be exploited will be in clear text. This section involves creating a “Static Virtual Channel” named “MS_T120.” The NCC Group wrote a Suricata signature which looks for this activity. Netresec offered a Wireshark display filter — rdp.​name == “MS_T120” — which will also find this event.

Identifying systems that may have been exploited will probably require analyzing traffic patterns between systems running RDS and those attacking from the Internet. Security analysts can review Corelight logs for unexpected interactions between remote IP addresses and enterprise RDS servers. Because Corelight logs are timestamped and interlinked via UID, incident responders can use those values to identify the scope of an intrusion.

In addition to suspicious IP addresses, security analysts can leverage other aspects of Corelight logs once they have a thread to follow. For example, RDS clients (who would be attackers in this case), reveal information about themselves via the “cookie” they present, as rendered in the rdp.log. Remember, this appeared as “cookie”:”DESKTOP-C” in our examples.

Conclusion

CVE-2019-0708 is a serious vulnerability awaiting exploitation. At the time of writing, no public proofs of concept were circulating, but this could change very quickly. Patching vulnerable servers is the best defense, but that requires first identifying all vulnerable RDS servers. That should not be taken for granted in enterprises of any significant size. Given the complexity of the modern information technology environment, it is prudent to complement asset inventory and patch management processes with network security monitoring people, processes, and technology to give defenders their best chances against prolific intruders.