Add initial support for better RMI calls
This commit is contained in:
parent
ac0e23d783
commit
0a37df67a0
|
@ -76,6 +76,7 @@ require 'msf/http/jboss'
|
|||
require 'msf/kerberos/client'
|
||||
|
||||
# Java RMI Support
|
||||
require 'msf/java/rmi/util'
|
||||
require 'msf/java/rmi/client'
|
||||
|
||||
# Java JMX Support
|
||||
|
|
|
@ -9,7 +9,9 @@ module Msf
|
|||
module Client
|
||||
|
||||
require 'msf/java/rmi/client/streams'
|
||||
require 'msf/java/rmi/util'
|
||||
|
||||
include Msf::Java::Rmi::Util
|
||||
include Msf::Java::Rmi::Client::Streams
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
|
|
|
@ -30,17 +30,49 @@ module Msf
|
|||
|
||||
# Builds a RMI call stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <Fixnum, Rex::Java::Serialization::Model::Stream>}]
|
||||
# @param opts [Hash{Symbol => <Fixnum, Array>}]
|
||||
# @option opts [Fixnum] :message_id
|
||||
# @option opts [Rex::Java::Serialization::Model::Stream] :call_data
|
||||
# @option opts [Fixnum] :object_number Random to identify the object.
|
||||
# @option opts [Fixnum] :uid_number Identifies the VM where the object was generated.
|
||||
# @option opts [Fixnum] :uid_time Time where the object was generated.
|
||||
# @option opts [Fixnum] :uid_count Identifies different instance of the same object generated from the same VM
|
||||
# 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
|
||||
# representing the method to call.
|
||||
# @option opts [Array] :arguments
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
def build_call(opts = {})
|
||||
message_id = opts[:message_id] || Rex::Proto::Rmi::Model::CALL_MESSAGE
|
||||
call_data = opts[:call_data] || Rex::Java::Serialization::Model::Stream.new
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
operation = opts[:operation] || -1
|
||||
method_hash = opts[:method_hash] || 0
|
||||
arguments = opts[:arguments] || []
|
||||
|
||||
block_data = Rex::Java::Serialization::Model::BlockData.new
|
||||
block_data.contents = [
|
||||
object_number,
|
||||
uid_number,
|
||||
uid_time,
|
||||
uid_count,
|
||||
operation,
|
||||
method_hash
|
||||
].pack('qlqslq')
|
||||
block_data.length = block_data.contents.length
|
||||
|
||||
call_data = Rex::Java::Serialization::Model::Stream.new
|
||||
call_data.contents << block_data
|
||||
arguments.each do |arg|
|
||||
call_data.contents << arg
|
||||
end
|
||||
|
||||
call = Rex::Proto::Rmi::Model::Call.new(
|
||||
message_id: message_id,
|
||||
call_data: call_data
|
||||
message_id: message_id,
|
||||
call_data: call_data
|
||||
)
|
||||
|
||||
call
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/java/serialization'
|
||||
require 'rex/text'
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Util
|
||||
# Calculates a method hash to make RMI calls as defined by the JDK 1.2
|
||||
#
|
||||
# @param signature [String] The remote method signature as specified by the JDK 1.2,
|
||||
# method name + method descriptor (as explained in the Java Virtual Machine Specification)
|
||||
# @return [Fixnum] The method hash
|
||||
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how method hashes are calculated
|
||||
def calculate_method_hash(signature)
|
||||
utf = Rex::Java::Serialization::Model::Utf.new(nil, signature)
|
||||
sha1 = Rex::Text.sha1_raw(utf.encode)
|
||||
|
||||
sha1.unpack('Q<')[0]
|
||||
end
|
||||
|
||||
# Calculates an interface hash to make RMI calls as defined by the JDK 1.1
|
||||
#
|
||||
# @param methods [Array] set of method names and their descriptors
|
||||
# @param exceptions [Array] set of declared exceptions
|
||||
# @return [Fixnum] The interface hash
|
||||
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how interface hashes are calculated
|
||||
def calculate_interface_hash(methods, exceptions)
|
||||
stream = ''
|
||||
stream << [1].pack('N') # stub version number
|
||||
|
||||
methods.each do |m|
|
||||
utf_method = Rex::Java::Serialization::Model::Utf.new(nil, m[:name])
|
||||
utf_descriptor = Rex::Java::Serialization::Model::Utf.new(nil, m[:descriptor])
|
||||
stream << utf_method.encode
|
||||
stream << utf_descriptor.encode
|
||||
exceptions.each do |e|
|
||||
utf_exception = Rex::Java::Serialization::Model::Utf.new(nil, e)
|
||||
stream << utf_exception.encode
|
||||
end
|
||||
end
|
||||
|
||||
sha1 = Rex::Text.sha1_raw(stream)
|
||||
|
||||
sha1.unpack('Q<')[0]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -51,7 +51,27 @@ class Metasploit3 < Msf::Auxiliary
|
|||
jar = Rex::Text.rand_text_alpha(rand(8)+1) + '.jar'
|
||||
jar_url = "file:RMIClassLoaderSecurityTest/" + jar
|
||||
|
||||
send_call(call_data: build_gc_call_data(jar_url))
|
||||
print_status(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;'}
|
||||
],
|
||||
['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))
|
||||
send_call(
|
||||
object_number: 2,
|
||||
uid_number: 0,
|
||||
uid_time: 0,
|
||||
uid_count: 0,
|
||||
operation: 0,
|
||||
method_hash: 0xf6b6898d8bf28643,
|
||||
arguments: build_dgc_clean_args(jar_url)
|
||||
)
|
||||
return_data = recv_return
|
||||
|
||||
if return_data.nil?
|
||||
|
@ -90,14 +110,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
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
|
||||
# class: sun.rmi.trasnport.DGC
|
||||
# method: public void clean(ObjID[] paramArrayOfObjID, long paramLong, VMID paramVMID, boolean paramBoolean)
|
||||
def build_dgc_clean_args(jar_url)
|
||||
arguments = []
|
||||
|
||||
new_array_annotation = Rex::Java::Serialization::Model::Annotation.new
|
||||
new_array_annotation.contents = [
|
||||
|
@ -124,8 +140,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
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")
|
||||
# ObjID[] paramArrayOfObjID
|
||||
arguments << new_array
|
||||
|
||||
# long paramLong
|
||||
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')
|
||||
|
@ -145,11 +164,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
new_object.class_desc.description = new_class_desc
|
||||
new_object.class_data = []
|
||||
|
||||
stream.contents << new_object
|
||||
# VMID paramVMID
|
||||
arguments << new_object
|
||||
|
||||
stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00")
|
||||
# boolean paramBoolean
|
||||
arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00")
|
||||
|
||||
stream
|
||||
arguments
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue