BlueKeep (CVE 2019-0708) exploitation spotted in the wild

Overview

It has been almost six months since an eye opening vulnerability in Microsoft Windows RDP CVE 2019-0708, dubbed BlueKeep, was patched. Today, Security Researcher Kevin Beaumont posted a Twitter thread reporting BSODs (Blue Screen of Death) across his network of BlueKeep Honeypots.

huh, the EternalPot RDP honeypots have all started BSOD’ing recently. They only expose port 3389. pic.twitter.com/VdiKoqAwkr

— Kevin Beaumont (@GossiTheDog) November 2, 2019

Kevin kindly shared the crash dump with us and following this lead, we discovered the sample was being used in a mass exploitation attempt. Due to only smaller size kernel dumps being enabled, it is difficult to arrive at a definite root cause.

Crash dump callstack

From initial observation, the call stack of the analysis seems off. Notably, the address 0x1aec08 is not allocated, or not present in the dump. Instead, We decided to look at pool allocations with the TSic tag, which is the pool tag used by IcaAllocateChannel in termdd.sys, the Windows RDP driver.

A snippet of allocations with the tag `TSic`

Looking at the TSic allocations, it’s clear something is off. Under normal circumstances there should be fewer than 100 allocations with the TSic tag, but in this case there are over 19,000, suggesting exploitation.

In particular, the allocations of size 0x170 stand out. From previous BlueKeep research, we know the size 0x170 is the exact size of the channel structure (plus metadata). During BlueKeep exploitation, the MS_T120 channel struct is freed, leaving a dangling pointer. To exploit the vulnerability, one must fill the memory hole with an allocation of 0x170 bytes. The thousands of allocations of 0x170 bytes suggest the exploitation technique of heap spraying, so let’s look deeper and verify.

Inside one of the 0x170 byte allocations

As anticipated, the allocation is a valid channel structure for the exploitable MS_T120 channel.

At offset 0x100 into the channel struct, there is an indirect pointer to a function. To gain Remote Code Execution (RCE), the attacker must hijack this pointer to lead to their shellcode, so it is crucial now to determine if it is set.

Indeed, we find it is set. If this is a BlueKeep exploit, we should find that dereferencing the address fffffa80`08807048 will lead to the payload or exploit shellcode.

Dereferencing the pointer

Finally, we confirm this segment points to executable shellcode. At this point we can assert valid BlueKeep exploit attempts in the wild, with shellcode that even matches that of the shellcode in the BlueKeep metasploit module!

Side by side of the in-memory shellcode and the metasploit shellcode

The snippet of shellcode does a simple “egghunt” (scans the system memory for a binary signature) to find the rest of the shellcode. The “egg” is 0x0b00dac0fefe42069. By scanning the memory for this value, we’ll find the rest of the shellcode.

Occurrences of the "egg"

There are hundreds of copies of the signature in memory, which is consistent with heap spraying.

Second part of the kernel shellcode

Again, the second part of the shellcode also matches that from the BlueKeep metasploit module. Seeing as most of the exploit shellcode seems to match that of metasploit, it can be assumed the usermode shellcode egg would be unchanged. Checking this we did the same memory scan but this time for the usermode egg 0xb00dac0fefe31337.

Usermode Shellcode

Not only was the egg the same, but the payload is easily visible at the end of shellcode. It’s an encoded PowerShell command.

First of the PowerShell nesting dolls

By decoding the PowerShell command, we obtain code to download another PowerShell command from the attacker’s server.

After this, another encoded PowerShell command is downloaded. And another. Eventually we arrive at the command which downloads and executes an actual executable binary.

The last stage of the PowerShell nesting dolls

This binary’s hash is known to VirusTotal as a cryptocurrency miner.

Conclusion

It is curious that this publicly known wormable vulnerability, known to everyone who would care to know for at least six months, took this long to get detectably weaponized. One might theorize that attackers know they have essentially one shot at using it at scale, and it becomes a game of chicken as to who will do it first. It is also worth noting that mass exploitation for gain can be difficult, owing to the risks involved.

Although this alleged activity is concerning, the information security community (correctly) predicted much worse potential scenarios. Based on our data we are not seeing a spike in indiscriminate scanning on the vulnerable port like we saw when EternalBlue was wormed across the Internet in what is now known as the WannaCry attack. It seems likely that a low-level actor scanned the Internet and opportunistically infected vulnerable hosts using out-of-the-box penetration testing utilities.