Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/ftp/ftp_login.rb
28052 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'metasploit/framework/credential_collection'
7
require 'metasploit/framework/login_scanner/ftp'
8
9
class MetasploitModule < Msf::Auxiliary
10
include Msf::Exploit::Remote::Ftp
11
include Msf::Auxiliary::Scanner
12
include Msf::Auxiliary::Report
13
include Msf::Auxiliary::AuthBrute
14
15
def proto
16
'ftp'
17
end
18
19
def initialize
20
super(
21
'Name' => 'FTP Authentication Scanner',
22
'Description' => %q{
23
This module will test FTP logins on a range of machines and
24
report successful logins. If you have loaded a database plugin
25
and connected to a database this module will record successful
26
logins and hosts so you can track your access.
27
},
28
'Author' => 'todb',
29
'References' => [
30
[ 'CVE', '1999-0502'] # Weak password
31
],
32
'License' => MSF_LICENSE,
33
'DefaultOptions' => {
34
'ConnectTimeout' => 30
35
}
36
)
37
38
register_options(
39
[
40
Opt::Proxies,
41
Opt::RPORT(21),
42
OptBool.new('RECORD_GUEST', [ false, "Record anonymous/guest logins to the database", false])
43
]
44
)
45
46
register_advanced_options(
47
[
48
OptBool.new('SINGLE_SESSION', [ false, 'Disconnect after every login attempt', false]),
49
]
50
)
51
52
deregister_options('FTPUSER', 'FTPPASS') # Can use these, but should use 'username' and 'password'
53
@accepts_all_logins = {}
54
end
55
56
def run_host(ip)
57
print_status("#{ip}:#{rport} - Starting FTP login sweep")
58
59
cred_collection = build_credential_collection(
60
username: datastore['USERNAME'],
61
password: datastore['PASSWORD'],
62
prepended_creds: anonymous_creds
63
)
64
65
scanner = Metasploit::Framework::LoginScanner::FTP.new(
66
configure_login_scanner(
67
host: ip,
68
port: rport,
69
proxies: datastore['PROXIES'],
70
cred_details: cred_collection,
71
stop_on_success: datastore['STOP_ON_SUCCESS'],
72
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
73
max_send_size: datastore['TCP::max_send_size'],
74
send_delay: datastore['TCP::send_delay'],
75
connection_timeout: datastore['ConnectTimeout'],
76
ftp_timeout: datastore['FTPTimeout'],
77
framework: framework,
78
framework_module: self,
79
ssl: datastore['SSL'],
80
ssl_version: datastore['SSLVersion'],
81
ssl_verify_mode: datastore['SSLVerifyMode'],
82
ssl_cipher: datastore['SSLCipher'],
83
local_port: datastore['CPORT'],
84
local_host: datastore['CHOST']
85
)
86
)
87
88
scanner.scan! do |result|
89
credential_data = result.to_h
90
credential_data.merge!(
91
module_fullname: self.fullname,
92
workspace_id: myworkspace_id
93
)
94
if result.success?
95
credential_data[:private_type] = :password
96
credential_core = create_credential(credential_data)
97
credential_data[:core] = credential_core
98
create_credential_login(credential_data)
99
100
print_good "#{ip}:#{rport} - Login Successful: #{result.credential}"
101
else
102
invalidate_login(credential_data)
103
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
104
end
105
end
106
end
107
108
# Always check for anonymous access by pretending to be a browser.
109
def anonymous_creds
110
anon_creds = [ ]
111
if datastore['RECORD_GUEST']
112
['IEUser@', 'User@', '[email protected]', '[email protected]' ].each do |password|
113
anon_creds << Metasploit::Framework::Credential.new(public: 'anonymous', private: password)
114
end
115
end
116
anon_creds
117
end
118
119
def test_ftp_access(user, scanner)
120
dir = Rex::Text.rand_text_alpha(8)
121
write_check = scanner.send_cmd(['MKD', dir], true)
122
if write_check and write_check =~ /^2/
123
scanner.send_cmd(['RMD', dir], true)
124
print_status("#{rhost}:#{rport} - User '#{user}' has READ/WRITE access")
125
return 'Read/Write'
126
else
127
print_status("#{rhost}:#{rport} - User '#{user}' has READ access")
128
return 'Read-only'
129
end
130
end
131
132
end
133
134