diff --git a/lib/msf/java/rmi/client/registry/parser.rb b/lib/msf/java/rmi/client/registry/parser.rb index bac4b39cce..d60c29e408 100644 --- a/lib/msf/java/rmi/client/registry/parser.rb +++ b/lib/msf/java/rmi/client/registry/parser.rb @@ -25,6 +25,37 @@ module Msf end end + def parse_registry_lookup_endpoint(return_value) + if return_value.nil? || return_value.is_exception? + return nil + end + + values_size = return_value.value.length + end_point_block_data = return_value.value[values_size - 2] + unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData) + return nil + end + + return_io = StringIO.new(end_point_block_data.contents, 'rb') + + ref = extract_string(return_io) + unless ref && ref == 'UnicastRef' + return nil + end + + address = extract_string(return_io) + return nil unless address + + port = extract_int(return_io) + return nil unless port + + object_number = extract_long(return_io) + + uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(return_io) + + {address: address, port: port, object_number: object_number, uid: uid} + end + def parse_registry_list(return_value) if return_value.nil? || return_value.is_exception? return nil diff --git a/lib/msf/java/rmi/util.rb b/lib/msf/java/rmi/util.rb index a1b8366518..5576dd9d7e 100644 --- a/lib/msf/java/rmi/util.rb +++ b/lib/msf/java/rmi/util.rb @@ -43,6 +43,53 @@ module Msf sha1.unpack('Q<')[0] end + + # Extracts an string from an IO + # + # @param io [IO] the io to extract the string from + # @return [String, nil] the extracted string if success, nil otherwise + def extract_string(io) + raw_length = io.read(2) + unless raw_length && raw_length.length == 2 + return nil + end + length = raw_length.unpack('s>')[0] + + string = io.read(length) + unless string && string.length == length + return nil + end + + string + end + + # Extracts an int from an IO + # + # @param io [IO] the io to extract the int from + # @return [Fixnum, nil] the extracted int if success, nil otherwise + def extract_int(io) + int_raw = io.read(4) + unless int_raw && int_raw.length == 4 + return nil + end + int = int_raw.unpack('l>')[0] + + int + end + + # Extracts a long from an IO + # + # @param io [IO] the io to extract the long from + # @return [Fixnum, nil] the extracted int if success, nil otherwise + def extract_long(io) + int_raw = io.read(8) + unless int_raw && int_raw.length == 8 + return nil + end + int = int_raw.unpack('q>')[0] + + int + end end end end diff --git a/modules/auxiliary/gather/java_rmi_registry.rb b/modules/auxiliary/gather/java_rmi_registry.rb index 6aa91130b7..256bf417b3 100644 --- a/modules/auxiliary/gather/java_rmi_registry.rb +++ b/modules/auxiliary/gather/java_rmi_registry.rb @@ -13,15 +13,19 @@ class Metasploit3 < Msf::Auxiliary def initialize super( - 'Name' => 'Java RMI Registry Endpoint Information Gathering', + 'Name' => 'Java RMI Registry Interfaces Enumeration', + 'Description' => %q{ + This module gathers information from an RMI endpoint running an RMI registry + interface. It enumerates the names bound into a registry and lookups each + remote reference. + }, 'Description' => 'Information gathering from Java RMI Registry endpoints', - 'Author' => ['juan vazquez'], + 'Author' => ['juan vazquez'], 'License' => MSF_LICENSE, - 'References' => + 'References' => [ - [ 'URL', 'http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmiTOC.html'] - ], - 'DisclosureDate' => 'Mar 18 2015' + ['URL', 'http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmiTOC.html'] + ] ) register_options( @@ -58,10 +62,27 @@ class Metasploit3 < Msf::Auxiliary print_good("#{peer} - #{names.length} names found in the Registry") names.each do |name| - object = send_registry_lookup(name: name) - next if object.nil? - print_good("#{peer} - name: #{name} remote object: #{object}") - #report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "#{name} / #{object}") + lookup_call = build_registry_lookup(name: name) + send_call(call: lookup_call) + return_value = recv_return + if return_value.nil? + print_error("#{peer} - Failed to lookup #{name}") + next + end + + remote_stub = parse_registry_lookup(return_value) + if remote_stub.nil? + print_error("#{peer} - Failed to lookup #{name}") + next + end + + location = parse_registry_lookup_endpoint(return_value) + if location.nil? + print_error("#{peer} - Failed to locate #{name} / #{remote_stub}") + end + + print_good("#{peer} - Name #{name} (#{remote_stub}) found on #{location[:address]}:#{location[:port]}") + report_service(:host => location[:address], :port => location[:port], :name => 'java-rmi', :info => "Name: #{name}, Stub: #{remote_stub}") end end end