Last updated
Last updated
CVE 2019-0708 (aka BlueKeep) is a security vulnerability in Microsoft Remote Desktop Services that has been published on May 14, 2019. This vulnerability has a CVSS Score of 10 which means possibility of remote access, code execution without any authentication on a target and without user interaction.
A remote code execution vulnerability exists in Remote Desktop Services – formerly known as Terminal Services – when an unauthenticated attacker connects to the target system using RDP and sends specially crafted requests. This vulnerability is pre-authentication and requires no user interaction. An attacker who successfully exploited this vulnerability could execute arbitrary code on the target system. An attacker could then install programs; view, change, or delete data; or create new accounts with full user rights.
More information about CVE 2019-0708 here :
On September 6, 2019 a Metasploit exploit module for BlueKeep has been release (Initialy developed by zerosum0x0). This module allow more or less easy exploitation of BlueKeep vulnerability as some configuration/information are needed. In fact, the start address of the Non Paged Pool (NPP) area need to be adjusted to minimize the risk of BSOD during the exploit.
Adjustement of NPP doesn't completely remove the risk of BSOD.
More information on Metasploit BlueKeep exploit here :
So, the first step to maximize chances to successfully exploit the BlueKeep vulnerability is to extract the NPP start address from Windows 7 target virtual machine. (At this time my Lab is on VMware Workstation 15.5.1)
Start by taking a Snapshot of target VM, then dump memory from the Snapshot with the following command :
A memory dump file "memory.dmp" will be created in current folder (In this case "Documents").
Open "memory.dmp" with WinDbg (File > Open Dump File) and launch the following command :
Now that the NPP Start Address has been extracted, GROOMBASE value in Bluekeep exploit module need to be adjusted :
Win7 Target IP Address : 192.168.126.43
Linux Attacker IP Address : 192.168.126.44
In order to run the BlueKeep exploit, launch msfconsole and use the following commands :
Exploit should run successfully :
The Windows 7 Target machine will generate some interesting events as result of the exploit, and in particular :
Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational : EventID 1149
Microsoft-Windows-Sysmon/Operational : EventID 3
Microsoft-Windows-Sysmon/Operational : EventID 1
These events will be usefull to create a Detection Rule for Bluekeep Scan and Exploit.
This part describe how events from Bluekeep target machine are sent to data pipeline to be indexed in Elasticsearch for investigation in one side and processed by Flink for pattern detection on the other side.
Sysmon and Windows events are sent to Logstash with Winlogbeat. There are several advantages to using Winlogbeat, it's possible to preprocess events, to choose desired codec, events are already in ECS (Elastic Common Schema) format, Elastic SIEM module will be easily usable, ...
Logstash will apply some logic (Tagging, processing, enrichment, ...) and then pushed/published events to Apache Kafka topics following their type/tags.
Flink will consume events in Kafka topic "Winlog topic" though "Winlog Stream".
On one side, events will be sent directly to Elasticsearch though an ElasticsearchSink, for future investigation and visualization.
On another side, events will be sent to "Pattern Stream" in order to detect a Bluekeep scans and exploits following results of multiple processing and a predefined pattern.
If/When events in "Pattern Stream" match the predefined pattern sequence, an "Alert Stream" containing events that triggered the detection rule is created.
An alert containing information from events (IP Adresses, Hostname, Network information, and so on...) is sent from the "Alert Stream" to Elasticsearch though an ElasticsearchSink for future investigation and visualization.
First thing to notice in events generated by the Windows 7 target machine, is that the BlueKeep Scanner randomly generate User and Domain name. It's possible to retrieve these information in EventID 1149.
Example :
In order to detect these randomly generated User and Domain, it's possible to use Markov Chain.
The goal here will be to divide User and Domain name in nGram (BiGram in our case) and compute the probability that each BiGram has to follow the previous BiGram.
Once probability has been computed, it's compared to a previous computed probability from a known list of non-randomly generated User and Domain name.
Obviously this method is not foolproof but with a good list User and Domain name non-randomly generated to "train" the model before, result are pretty good.
More information on Markov Chain here :
It's a broad summary but the main idea of how code works is here :
Create a 2D Matrix following an alphabet in our case "a-zA-Z0-9 " (63 characters with space) and fill the "Alphabet Matrix" with a minimum count.
Split username in nGram (Bigram ex: "johndoe" : [jo][oh][hn][nd][do][oe]) from a list of known username (For example extracted from Directory Service or created from list of well known Last and First name from different country) and fill the "Alphabet Matrix" with the number of time each character of nGram appear in each position (For Bigram, first or second position).
Create a 2D "Probability Matrix" from the "Alphabet Matrix" by turning counts in probability.
Get a threshold value (Average) from lists of known randomly and non-randomly generated strings following the "Probability Matrix".
Compare new strings to the threshold value to determine if those ones may have been randomly or non-randomly generated.
Here is how the detection rule works :
In the case of Iterative Condition, events will be processed only if a condition has been previously met.
Example with Pattern "Bluekeep Scan EID 1149" :
In this case, if an event from the "Winlog Stream" have an EventID not equals to "1149", false is return, username will not be processed to check if it's a random or non-random string and events will not go though the next Pattern (or condition).
So, to go to the next Pattern an event will have to have an EventID equals to 1149 AND a Username detected as randomly generated.
It's usefull to compare values between events within the same rule, for example to ensure that there is a correlation between multiple events.
Example with Pattern "Bluekeep Scan EID 3" :
On the Pattern "Bluekeep Scan EID 3" we want to check if "Source IP" from EventID 1149 found in previous pattern has established a connection. For that, we check if next event has an EventID equals to 3 and then we retrieve "SourceIP" from previous Pattern with "context.getEventsForPattern($PatternName)" and compare this value to "SourceIP" value in current Pattern events.
If events in events stream match a full Pattern sequence (a succession of simple pattern) then corresponding events will be store in a list and accessible though a new stream and by using function "PatternSelectFunction".
So, events are now stored in a Map where key is the Pattern name from where event(s) is/are and value(s) is/are the original(s) event(s).
It's possible to retrieve values in each events to create an alert, for example :
Here we get "Process ID" from each events of each patterns by specifying the name of the Pattern first and then the value we want to get from the JSON (ObjectNode here).
Once all relevant informations have been retrieved from events that matched with the Pattern sequence and perhaps have added other information from other sources or from static values, alerts can be sent to Elasticsearch though an ElasticsearchSink.
Alerts are sent as JSON String, so to be correctly "Parsed" and indexed by Elasticsearch those ones have to be mapped before to be indexed :
WinDbg can be downloaded here :
For this part I reused the code from "Gibberish-Detector" on Paypal GitHub here : that is a portage in Java from Python code here : . I just added some comments to make it more clear and easier to read.
Markov Chain Java code used along Flink CEP Library for Bluekeep detection rule POC can be found here :
This page describe how to use Apache Kafka, Apache Flink and Elastic Stack and Markov Chain to detect BlueKeep vulnerability scan and exploit.