105 lines
3.0 KiB
Ruby
105 lines
3.0 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
include Msf::Exploit::Remote::Tcp
|
|
include Msf::Auxiliary::Scanner
|
|
include Msf::Auxiliary::Report
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Identify endpoints speaking the Remote Desktop Protocol (RDP)',
|
|
'Description' => %q(
|
|
This module attempts to connect to the specified Remote Desktop Protocol port
|
|
and determines if it speaks RDP.
|
|
),
|
|
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
|
|
'References' =>
|
|
[
|
|
['URL', 'https://msdn.microsoft.com/en-us/library/cc240445.aspx']
|
|
],
|
|
'License' => MSF_LICENSE
|
|
)
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
Opt::RPORT(3389),
|
|
OptBool.new('TLS', [true, 'Wheter or not request TLS security', true]),
|
|
OptBool.new('CredSSP', [true, 'Whether or not to request CredSSP', true]),
|
|
OptBool.new('EarlyUser', [true, 'Whether to support Earlier User Authorization Result PDU', false])
|
|
]
|
|
)
|
|
end
|
|
|
|
# any TPKT v3 + x.2224 COTP Connect Confirm
|
|
RDP_RE = /^\x03\x00.{3}\xd0.{5}.*$/
|
|
def rdp?
|
|
sock.put(@probe)
|
|
response = sock.get_once(-1)
|
|
if response
|
|
if RDP_RE.match(response)
|
|
# XXX: it might be helpful to decode the response and show what was selected.
|
|
print_good("Identified RDP")
|
|
return true
|
|
else
|
|
vprint_status("No match for '#{Rex::Text.to_hex_ascii(response)}'")
|
|
end
|
|
else
|
|
vprint_status("No response")
|
|
end
|
|
end
|
|
|
|
def setup
|
|
# build a simple TPKT v3 + x.224 COTP Connect Request. optionally append
|
|
# RDP negotiation request with TLS, CredSSP and Early User as requesteste
|
|
requested_protocols = 0
|
|
if datastore['TLS']
|
|
requested_protocols = requested_protocols ^ 0b1
|
|
end
|
|
if datastore['CredSSP']
|
|
requested_protocols = requested_protocols ^ 0b10
|
|
end
|
|
if datastore['EarlyUser']
|
|
requested_protocols = requested_protocols ^ 0b1000
|
|
end
|
|
|
|
if requested_protocols == 0
|
|
tpkt_len = 11
|
|
cotp_len = 6
|
|
pack = [ 3, 0, tpkt_len, cotp_len, 0xe0, 0, 0, 0 ]
|
|
pack_string = "CCnCCnnC"
|
|
else
|
|
tpkt_len = 19
|
|
cotp_len = 14
|
|
pack = [ 3, 0, tpkt_len, cotp_len, 0xe0, 0, 0, 0, 1, 0, 8, 0, requested_protocols ]
|
|
pack_string = "CCnCCnnCCCCCV"
|
|
end
|
|
@probe = pack.pack(pack_string)
|
|
end
|
|
|
|
def run_host(_ip)
|
|
begin
|
|
connect
|
|
return unless rdp?
|
|
rescue Rex::AddressInUse, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, \
|
|
::Errno::ETIMEDOUT, ::Timeout::Error, ::EOFError => e
|
|
vprint_error("error while connecting and negotiating RDP: #{e}")
|
|
return
|
|
ensure
|
|
disconnect
|
|
end
|
|
|
|
report_service(
|
|
host: rhost,
|
|
port: rport,
|
|
proto: 'tcp',
|
|
name: 'RDP'
|
|
)
|
|
end
|
|
end
|