This Metasploit module will test FTP logins on a range of machines and report successful logins. If you have loaded a database plugin and connected to a database this module will record successful logins and hosts so you can track your access.
65e04ec1ca6df75366ef90e58cffc41dcbaf3395a13653f08ad81ab38759c904
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/ftp'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Ftp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
def proto
'ftp'
end
def initialize
super(
'Name' => 'FTP Authentication Scanner',
'Description' => %q{
This module will test FTP logins on a range of machines and
report successful logins. If you have loaded a database plugin
and connected to a database this module will record successful
logins and hosts so you can track your access.
},
'Author' => 'todb',
'References' =>
[
[ 'CVE', '1999-0502'] # Weak password
],
'License' => MSF_LICENSE,
'DefaultOptions' => {
'ConnectTimeout' => 30
}
)
register_options(
[
Opt::Proxies,
Opt::RPORT(21),
OptBool.new('RECORD_GUEST', [ false, "Record anonymous/guest logins to the database", false])
])
register_advanced_options(
[
OptBool.new('SINGLE_SESSION', [ false, 'Disconnect after every login attempt', false]),
]
)
deregister_options('FTPUSER','FTPPASS') # Can use these, but should use 'username' and 'password'
@accepts_all_logins = {}
end
def run_host(ip)
print_status("#{ip}:#{rport} - Starting FTP login sweep")
cred_collection = build_credential_collection(
username: datastore['USERNAME'],
password: datastore['PASSWORD'],
prepended_creds: anonymous_creds
)
scanner = Metasploit::Framework::LoginScanner::FTP.new(
configure_login_scanner(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
max_send_size: datastore['TCP::max_send_size'],
send_delay: datastore['TCP::send_delay'],
connection_timeout: datastore['ConnectTimeout'],
ftp_timeout: datastore['FTPTimeout'],
framework: framework,
framework_module: self,
ssl: datastore['SSL'],
ssl_version: datastore['SSLVersion'],
ssl_verify_mode: datastore['SSLVerifyMode'],
ssl_cipher: datastore['SSLCipher'],
local_port: datastore['CPORT'],
local_host: datastore['CHOST']
)
)
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: self.fullname,
workspace_id: myworkspace_id
)
if result.success?
credential_data[:private_type] = :password
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good "#{ip}:#{rport} - Login Successful: #{result.credential}"
else
invalidate_login(credential_data)
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end
# Always check for anonymous access by pretending to be a browser.
def anonymous_creds
anon_creds = [ ]
if datastore['RECORD_GUEST']
['IEUser@', 'User@', 'mozilla@example.com', 'chrome@example.com' ].each do |password|
anon_creds << Metasploit::Framework::Credential.new(public: 'anonymous', private: password)
end
end
anon_creds
end
def test_ftp_access(user,scanner)
dir = Rex::Text.rand_text_alpha(8)
write_check = scanner.send_cmd(['MKD', dir], true)
if write_check and write_check =~ /^2/
scanner.send_cmd(['RMD',dir], true)
print_status("#{rhost}:#{rport} - User '#{user}' has READ/WRITE access")
return 'Read/Write'
else
print_status("#{rhost}:#{rport} - User '#{user}' has READ access")
return 'Read-only'
end
end
end