Move Msf::Java to the normal Msf::Exploit::Remote namespace
parent
5e9faad4dc
commit
cd2e9d4232
|
@ -75,10 +75,6 @@ require 'msf/http/jboss'
|
||||||
# Kerberos Support
|
# Kerberos Support
|
||||||
require 'msf/kerberos/client'
|
require 'msf/kerberos/client'
|
||||||
|
|
||||||
# Java RMI Support
|
|
||||||
require 'msf/java/rmi/util'
|
|
||||||
require 'msf/java/rmi/client'
|
|
||||||
|
|
||||||
# Drivers
|
# Drivers
|
||||||
require 'msf/core/exploit_driver'
|
require 'msf/core/exploit_driver'
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
###
|
###
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/exploit/java/rmi/util'
|
||||||
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
module Msf
|
module Msf
|
||||||
module Exploit::Java
|
module Exploit::Java
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'rex/java/serialization'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Builder
|
||||||
|
# Builds a RMI header stream
|
||||||
|
#
|
||||||
|
# @param opts [Hash{Symbol => <String, Fixnum>}]
|
||||||
|
# @option opts [String] :signature
|
||||||
|
# @option opts [Fixnum] :version
|
||||||
|
# @option opts [Fixnum] :protocol
|
||||||
|
# @return [Rex::Proto::Rmi::Model::OutputHeader]
|
||||||
|
def build_header(opts = {})
|
||||||
|
signature = opts[:signature] || Rex::Proto::Rmi::Model::SIGNATURE
|
||||||
|
version = opts[:version] || 2
|
||||||
|
protocol = opts[:protocol] || Rex::Proto::Rmi::Model::STREAM_PROTOCOL
|
||||||
|
|
||||||
|
header = Rex::Proto::Rmi::Model::OutputHeader.new(
|
||||||
|
signature: signature,
|
||||||
|
version: version,
|
||||||
|
protocol: protocol)
|
||||||
|
|
||||||
|
header
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds a RMI call stream
|
||||||
|
#
|
||||||
|
# @param opts [Hash{Symbol => <Fixnum, Array>}]
|
||||||
|
# @option opts [Fixnum] :message_id
|
||||||
|
# @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] :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
|
||||||
|
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
|
||||||
|
hash = opts[:hash] || 0
|
||||||
|
arguments = opts[:arguments] || []
|
||||||
|
|
||||||
|
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.new(
|
||||||
|
number: uid_number,
|
||||||
|
time: uid_time,
|
||||||
|
count: uid_count
|
||||||
|
)
|
||||||
|
|
||||||
|
call_data = Rex::Proto::Rmi::Model::CallData.new(
|
||||||
|
object_number: object_number,
|
||||||
|
uid: uid,
|
||||||
|
operation: operation,
|
||||||
|
hash: hash,
|
||||||
|
arguments: arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
call = Rex::Proto::Rmi::Model::Call.new(
|
||||||
|
message_id: message_id,
|
||||||
|
call_data: call_data
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds a RMI dgc ack stream
|
||||||
|
#
|
||||||
|
# @param opts [Hash{Symbol => <Fixnum, String>}]
|
||||||
|
# @option opts [Fixnum] :stream_id
|
||||||
|
# @option opts [String] :unique_identifier
|
||||||
|
# @return [Rex::Proto::Rmi::Model::DgcAck]
|
||||||
|
def build_dgc_ack(opts = {})
|
||||||
|
stream_id = opts[:stream_id] || Rex::Proto::Rmi::Model::DGC_ACK_MESSAGE
|
||||||
|
unique_identifier = opts[:unique_identifier] || "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
|
||||||
|
dgc_ack = Rex::Proto::Rmi::Model::DgcAck.new(
|
||||||
|
stream_id: stream_id,
|
||||||
|
unique_identifier: unique_identifier
|
||||||
|
)
|
||||||
|
|
||||||
|
dgc_ack
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,168 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
require 'rex/proto/rmi'
|
||||||
|
require 'rex/java/serialization'
|
||||||
|
require 'stringio'
|
||||||
|
require 'msf/core/exploit/java/rmi/util'
|
||||||
|
require 'msf/core/exploit/java/rmi/builder'
|
||||||
|
require 'msf/core/exploit/java/rmi/client/registry'
|
||||||
|
require 'msf/core/exploit/java/rmi/client/jmx'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Util
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Builder
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Registry
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx
|
||||||
|
include Msf::Exploit::Remote::Tcp
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super
|
||||||
|
|
||||||
|
register_advanced_options(
|
||||||
|
[
|
||||||
|
OptInt.new('RmiReadLoopTimeout', [ true, 'Maximum number of seconds to wait for data between read iterations', 1])
|
||||||
|
], Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the timeout to wait for data between read iterations
|
||||||
|
#
|
||||||
|
# @return [Fixnum]
|
||||||
|
def read_loop_timeout
|
||||||
|
datastore['RmiReadLoopTimeout'] || 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the target host
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def rhost
|
||||||
|
datastore['RHOST']
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the target port
|
||||||
|
#
|
||||||
|
# @return [Fixnum]
|
||||||
|
def rport
|
||||||
|
datastore['RPORT']
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the RMI server peer
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def peer
|
||||||
|
"#{rhost}:#{rport}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sends a RMI header stream
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Fixnum] the number of bytes sent
|
||||||
|
# @see Msf::Rmi::Client::Streams#build_header
|
||||||
|
def send_header(opts = {})
|
||||||
|
nsock = opts[:sock] || sock
|
||||||
|
stream = build_header(opts)
|
||||||
|
nsock.put(stream.encode + "\x00\x00\x00\x00\x00\x00")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sends a RMI CALL stream
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @option opts [Rex::Proto::Rmi::Model::Call] :call
|
||||||
|
# @return [Fixnum] the number of bytes sent
|
||||||
|
# @see Msf::Rmi::Client::Streams#build_call
|
||||||
|
def send_call(opts = {})
|
||||||
|
nsock = opts[:sock] || sock
|
||||||
|
call = opts[:call] || build_call(opts)
|
||||||
|
nsock.put(call.encode)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sends a RMI DGCACK stream
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Fixnum] the number of bytes sent
|
||||||
|
# @see Msf::Rmi::Client::Streams#build_dgc_ack
|
||||||
|
def send_dgc_ack(opts = {})
|
||||||
|
nsock = opts[:sock] || sock
|
||||||
|
stream = build_dgc_ack(opts)
|
||||||
|
nsock.put(stream.encode)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Reads the Protocol Ack
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Rex::Proto::Rmi::Model::ProtocolAck] if success
|
||||||
|
# @return [NilClass] otherwise
|
||||||
|
# @see Rex::Proto::Rmi::Model::ProtocolAck.decode
|
||||||
|
def recv_protocol_ack(opts = {})
|
||||||
|
nsock = opts[:sock] || sock
|
||||||
|
data = safe_get_once(nsock)
|
||||||
|
begin
|
||||||
|
ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data))
|
||||||
|
rescue Rex::Proto::Rmi::DecodeError
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
ack
|
||||||
|
end
|
||||||
|
|
||||||
|
# Reads a ReturnData message and returns the java serialized stream
|
||||||
|
# with the return data value.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Rex::Proto::Rmi::Model::ReturnValue] if success
|
||||||
|
# @return [NilClass] otherwise
|
||||||
|
# @see Rex::Proto::Rmi::Model::ReturnData.decode
|
||||||
|
def recv_return(opts = {})
|
||||||
|
nsock = opts[:sock] || sock
|
||||||
|
data = safe_get_once(nsock)
|
||||||
|
|
||||||
|
begin
|
||||||
|
return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data))
|
||||||
|
rescue Rex::Proto::Rmi::DecodeError
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return_data.return_value
|
||||||
|
end
|
||||||
|
|
||||||
|
# Helper method to read fragmented data from a ```Rex::Socket::Tcp```
|
||||||
|
#
|
||||||
|
# @param nsock [Rex::Socket::Tcp]
|
||||||
|
# @return [String]
|
||||||
|
def safe_get_once(nsock = sock, loop_timeout = read_loop_timeout)
|
||||||
|
data = ''
|
||||||
|
begin
|
||||||
|
res = nsock.get_once
|
||||||
|
rescue ::EOFError
|
||||||
|
res = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
while res && nsock.has_read_data?(loop_timeout)
|
||||||
|
data << res
|
||||||
|
begin
|
||||||
|
res = nsock.get_once
|
||||||
|
rescue ::EOFError
|
||||||
|
res = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
data << res if res
|
||||||
|
data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,27 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
require 'msf/core/exploit/java/rmi/client/jmx/server'
|
||||||
|
require 'msf/core/exploit/java/rmi/client/jmx/connection'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Jmx
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Connection
|
||||||
|
|
||||||
|
OBJECT_NAME_UID = 1081892073854801359
|
||||||
|
BYTE_ARRAY_UID = -5984413125824719648
|
||||||
|
MARSHALLED_OBJECT_UID = 8988374069173025854
|
||||||
|
STRING_ARRAY_UID = -5921575005990323385
|
||||||
|
OBJECT_ARRAY_UID = -8012369246846506644
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,128 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core/exploit/java/rmi/client/jmx/connection/builder'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Jmx
|
||||||
|
# This mixin provides methods to simulate calls to the Java
|
||||||
|
# javax/management/remote/rmi/RMIConnectionImpl_Stub
|
||||||
|
# interface
|
||||||
|
module Connection
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Connection::Builder
|
||||||
|
|
||||||
|
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
|
||||||
|
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
||||||
|
# method.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [TrueClass, NilClass] true if success, nil otherwise
|
||||||
|
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_get_object_instance
|
||||||
|
def send_jmx_get_object_instance(opts = {})
|
||||||
|
send_call(
|
||||||
|
sock: opts[:sock] || sock,
|
||||||
|
call: build_jmx_get_object_instance(opts)
|
||||||
|
)
|
||||||
|
|
||||||
|
return_value = recv_return(
|
||||||
|
sock: opts[:sock] || sock
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_value.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_value.is_exception?
|
||||||
|
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||||
|
end
|
||||||
|
|
||||||
|
unless return_value.get_class_name == 'javax.management.ObjectInstance'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sends a call to the JMXRMI endpoint to create an MBean instance. Simulates a call
|
||||||
|
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
||||||
|
# method.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [TrueClass, NilClass] true if success, nil otherwise
|
||||||
|
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_create_mbean
|
||||||
|
def send_jmx_create_mbean(opts = {})
|
||||||
|
send_call(
|
||||||
|
sock: opts[:sock] || sock,
|
||||||
|
call: build_jmx_create_mbean(opts)
|
||||||
|
)
|
||||||
|
|
||||||
|
return_value = recv_return(
|
||||||
|
sock: opts[:sock] || sock
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_value.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_value.is_exception?
|
||||||
|
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||||
|
end
|
||||||
|
|
||||||
|
unless return_value.get_class_name == 'javax.management.ObjectInstance'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sends a call to the JMXRMI endpoint to invoke an MBean method. Simulates a call
|
||||||
|
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||||
|
# method.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [TrueClass, NilClass] true if success, nil otherwise
|
||||||
|
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_invoke
|
||||||
|
def send_jmx_invoke(opts = {})
|
||||||
|
send_call(
|
||||||
|
sock: opts[:sock] || sock,
|
||||||
|
call: build_jmx_invoke(opts)
|
||||||
|
)
|
||||||
|
|
||||||
|
return_value = recv_return(
|
||||||
|
sock: opts[:sock] || sock
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_value.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_value.is_exception?
|
||||||
|
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||||
|
end
|
||||||
|
|
||||||
|
unless return_value.get_class_name == 'java.util.HashSet'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,238 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Jmx
|
||||||
|
module Connection
|
||||||
|
module Builder
|
||||||
|
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
||||||
|
# used to retrieve an MBean instance
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :name the MBean name
|
||||||
|
# @return [Rex::Proto::Rmi::Model::Call]
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
|
||||||
|
def build_jmx_get_object_instance(opts = {})
|
||||||
|
object_number = opts[:object_number] || 0
|
||||||
|
uid_number = opts[:uid_number] || 0
|
||||||
|
uid_time = opts[:uid_time] || 0
|
||||||
|
uid_count = opts[:uid_count] || 0
|
||||||
|
name = opts[:name] || ''
|
||||||
|
|
||||||
|
arguments = build_jmx_get_object_instance_args(name)
|
||||||
|
|
||||||
|
method_hash = calculate_method_hash('getObjectInstance(Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
|
||||||
|
|
||||||
|
call = build_call(
|
||||||
|
object_number: object_number,
|
||||||
|
uid_number: uid_number,
|
||||||
|
uid_time: uid_time,
|
||||||
|
uid_count: uid_count,
|
||||||
|
operation: -1,
|
||||||
|
hash: method_hash,
|
||||||
|
arguments: arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds an an array of arguments o build a call to
|
||||||
|
# javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
||||||
|
#
|
||||||
|
# @param name [String] the MBean name
|
||||||
|
# @return [Array]
|
||||||
|
def build_jmx_get_object_instance_args(name = '')
|
||||||
|
builder = Rex::Java::Serialization::Builder.new
|
||||||
|
|
||||||
|
new_object = builder.new_object(
|
||||||
|
name: 'javax.management.ObjectName',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
|
||||||
|
flags: 3
|
||||||
|
)
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
new_object,
|
||||||
|
Rex::Java::Serialization::Model::Utf.new(nil, name),
|
||||||
|
Rex::Java::Serialization::Model::EndBlockData.new,
|
||||||
|
Rex::Java::Serialization::Model::NullReference.new
|
||||||
|
]
|
||||||
|
|
||||||
|
arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
||||||
|
# used to retrieve an MBean instance
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :name the MBean name
|
||||||
|
# @return [Rex::Proto::Rmi::Model::Call]
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
|
||||||
|
def build_jmx_create_mbean(opts = {})
|
||||||
|
name = opts[:name] || ''
|
||||||
|
object_number = opts[:object_number] || 0
|
||||||
|
uid_number = opts[:uid_number] || 0
|
||||||
|
uid_time = opts[:uid_time] || 0
|
||||||
|
uid_count = opts[:uid_count] || 0
|
||||||
|
|
||||||
|
method_hash = calculate_method_hash('createMBean(Ljava/lang/String;Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
|
||||||
|
|
||||||
|
arguments = build_jmx_create_mbean_args(name)
|
||||||
|
|
||||||
|
call = build_call(
|
||||||
|
object_number: object_number,
|
||||||
|
uid_number: uid_number,
|
||||||
|
uid_time: uid_time,
|
||||||
|
uid_count: uid_count,
|
||||||
|
operation: -1,
|
||||||
|
hash: method_hash,
|
||||||
|
arguments: arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds an an array of arguments o build a call to
|
||||||
|
# javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
||||||
|
#
|
||||||
|
# @param name [Hash] the MBean name
|
||||||
|
# @return [Array]
|
||||||
|
def build_jmx_create_mbean_args(name = '')
|
||||||
|
arguments = [
|
||||||
|
Rex::Java::Serialization::Model::Utf.new(nil, name),
|
||||||
|
Rex::Java::Serialization::Model::NullReference.new,
|
||||||
|
Rex::Java::Serialization::Model::NullReference.new
|
||||||
|
]
|
||||||
|
|
||||||
|
arguments
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||||
|
# used to invoke an MBean method
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :name the MBean name
|
||||||
|
# @return [Rex::Proto::Rmi::Model::Call]
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
|
||||||
|
# @see #build_jmx_invoke_args
|
||||||
|
def build_jmx_invoke(opts = {})
|
||||||
|
object_number = opts[:object_number] || 0
|
||||||
|
uid_number = opts[:uid_number] || 0
|
||||||
|
uid_time = opts[:uid_time] || 0
|
||||||
|
uid_count = opts[:uid_count] || 0
|
||||||
|
|
||||||
|
method_hash = calculate_method_hash('invoke(Ljavax/management/ObjectName;Ljava/lang/String;Ljava/rmi/MarshalledObject;[Ljava/lang/String;Ljavax/security/auth/Subject;)Ljava/lang/Object;')
|
||||||
|
|
||||||
|
arguments = build_jmx_invoke_args(opts)
|
||||||
|
|
||||||
|
call = build_call(
|
||||||
|
object_number: object_number,
|
||||||
|
uid_number: uid_number,
|
||||||
|
uid_time: uid_time,
|
||||||
|
uid_count: uid_count,
|
||||||
|
operation: -1,
|
||||||
|
hash: method_hash,
|
||||||
|
arguments: arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds an an array of arguments o build a call to
|
||||||
|
# javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :object the MBean name
|
||||||
|
# @option opts [String] :method the method name
|
||||||
|
# @option opts [Hash] :args the method arguments
|
||||||
|
# @return [Array]
|
||||||
|
def build_jmx_invoke_args(opts = {})
|
||||||
|
object_name = opts[:object] || ''
|
||||||
|
method_name = opts[:method] || ''
|
||||||
|
args = opts[:args] || {}
|
||||||
|
|
||||||
|
builder = Rex::Java::Serialization::Builder.new
|
||||||
|
|
||||||
|
new_object = builder.new_object(
|
||||||
|
name: 'javax.management.ObjectName',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
|
||||||
|
flags: 3
|
||||||
|
)
|
||||||
|
|
||||||
|
data_binary = builder.new_array(
|
||||||
|
name: '[B',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::BYTE_ARRAY_UID, # serialVersionUID
|
||||||
|
values_type: 'byte',
|
||||||
|
values: build_invoke_arguments_obj_bytes(args).encode.unpack('C*')
|
||||||
|
)
|
||||||
|
|
||||||
|
marshall_object = builder.new_object(
|
||||||
|
name: 'java.rmi.MarshalledObject',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::MARSHALLED_OBJECT_UID, # serialVersionUID
|
||||||
|
fields: [
|
||||||
|
['int', 'hash'],
|
||||||
|
['array', 'locBytes', '[B'],
|
||||||
|
['array', 'objBytes', '[B']
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
["int", 1919492550],
|
||||||
|
Rex::Java::Serialization::Model::NullReference.new,
|
||||||
|
data_binary
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
new_array = builder.new_array(
|
||||||
|
name: '[Ljava.lang.String;',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
|
||||||
|
values_type: 'java.lang.String;',
|
||||||
|
values: args.keys.collect { |k| Rex::Java::Serialization::Model::Utf.new(nil, k) }
|
||||||
|
)
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
new_object,
|
||||||
|
Rex::Java::Serialization::Model::Utf.new(nil, object_name),
|
||||||
|
Rex::Java::Serialization::Model::EndBlockData.new,
|
||||||
|
Rex::Java::Serialization::Model::Utf.new(nil, method_name),
|
||||||
|
marshall_object,
|
||||||
|
new_array,
|
||||||
|
Rex::Java::Serialization::Model::NullReference.new
|
||||||
|
]
|
||||||
|
|
||||||
|
arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds a Rex::Java::Serialization::Model::Stream with the arguments to
|
||||||
|
# simulate a call to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||||
|
# method.
|
||||||
|
#
|
||||||
|
# @param args [Hash] the arguments of the method to invoke
|
||||||
|
# @return [Rex::Java::Serialization::Model::Stream]
|
||||||
|
def build_invoke_arguments_obj_bytes(args = {})
|
||||||
|
builder = Rex::Java::Serialization::Builder.new
|
||||||
|
|
||||||
|
new_array = builder.new_array(
|
||||||
|
name: '[Ljava.lang.Object;',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::OBJECT_ARRAY_UID, # serialVersionUID
|
||||||
|
annotations: [Rex::Java::Serialization::Model::EndBlockData.new],
|
||||||
|
values_type: 'java.lang.Object;',
|
||||||
|
values: args.values.collect { |arg| Rex::Java::Serialization::Model::Utf.new(nil, arg) }
|
||||||
|
)
|
||||||
|
|
||||||
|
stream = Rex::Java::Serialization::Model::Stream.new
|
||||||
|
stream.contents << new_array
|
||||||
|
|
||||||
|
stream
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,63 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core/exploit/java/rmi/client/jmx/server/builder'
|
||||||
|
require 'msf/core/exploit/java/rmi/client/jmx/server/parser'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Jmx
|
||||||
|
module Server
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server::Builder
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server::Parser
|
||||||
|
|
||||||
|
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
|
||||||
|
# to the Java javax/management/remote/rmi/RMIServer_Stub#newClient()
|
||||||
|
# method.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Hash, NilClass] The connection information if success, nil otherwise
|
||||||
|
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_new_client
|
||||||
|
def send_new_client(opts = {})
|
||||||
|
send_call(
|
||||||
|
sock: opts[:sock] || sock,
|
||||||
|
call: build_jmx_new_client(opts)
|
||||||
|
)
|
||||||
|
|
||||||
|
return_value = recv_return(
|
||||||
|
sock: opts[:sock] || sock
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_value.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_value.is_exception?
|
||||||
|
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||||
|
end
|
||||||
|
|
||||||
|
remote_object = return_value.get_class_name
|
||||||
|
|
||||||
|
unless remote_object && remote_object == 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
reference = parse_jmx_new_client_endpoint(return_value)
|
||||||
|
|
||||||
|
reference
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,77 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Jmx
|
||||||
|
module Server
|
||||||
|
module Builder
|
||||||
|
|
||||||
|
# Builds an RMI call to javax/management/remote/rmi/RMIServer_Stub#newClient()
|
||||||
|
# used to enumerate the names bound in a registry
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :username the JMX role to establish the connection if needed
|
||||||
|
# @option opts [String] :password the JMX password to establish the connection if needed
|
||||||
|
# @return [Rex::Proto::Rmi::Model::Call]
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
|
||||||
|
def build_jmx_new_client(opts = {})
|
||||||
|
object_number = opts[:object_number] || 0
|
||||||
|
uid_number = opts[:uid_number] || 0
|
||||||
|
uid_time = opts[:uid_time] || 0
|
||||||
|
uid_count = opts[:uid_count] || 0
|
||||||
|
username = opts[:username]
|
||||||
|
password = opts[:password] || ''
|
||||||
|
|
||||||
|
if username
|
||||||
|
arguments = build_jmx_new_client_args(username, password)
|
||||||
|
else
|
||||||
|
arguments = [Rex::Java::Serialization::Model::NullReference.new]
|
||||||
|
end
|
||||||
|
|
||||||
|
call = build_call(
|
||||||
|
object_number: object_number,
|
||||||
|
uid_number: uid_number,
|
||||||
|
uid_time: uid_time,
|
||||||
|
uid_count: uid_count,
|
||||||
|
operation: -1,
|
||||||
|
hash: -1089742558549201240, # javax.management.remote.rmi.RMIServer.newClient
|
||||||
|
arguments: arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds a Rex::Java::Serialization::Model::NewArray with credentials
|
||||||
|
# to make an javax/management/remote/rmi/RMIServer_Stub#newClient call
|
||||||
|
#
|
||||||
|
# @param username [String] The username (role) to authenticate with
|
||||||
|
# @param password [String] The password to authenticate with
|
||||||
|
# @return [Array<Rex::Java::Serialization::Model::NewArray>]
|
||||||
|
def build_jmx_new_client_args(username = '', password = '')
|
||||||
|
builder = Rex::Java::Serialization::Builder.new
|
||||||
|
|
||||||
|
auth_array = builder.new_array(
|
||||||
|
name: '[Ljava.lang.String;',
|
||||||
|
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
|
||||||
|
values_type: 'java.lang.String;',
|
||||||
|
values: [
|
||||||
|
Rex::Java::Serialization::Model::Utf.new(nil, username),
|
||||||
|
Rex::Java::Serialization::Model::Utf.new(nil, password)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
[auth_array]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,40 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Jmx
|
||||||
|
module Server
|
||||||
|
module Parser
|
||||||
|
# Parses a javax/management/remote/rmi/RMIServer_Stub#newClient() return value
|
||||||
|
# to find out the remote reference information.
|
||||||
|
#
|
||||||
|
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
||||||
|
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
|
||||||
|
def parse_jmx_new_client_endpoint(return_value)
|
||||||
|
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')
|
||||||
|
|
||||||
|
reference = extract_reference(return_io)
|
||||||
|
|
||||||
|
reference
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,135 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core/exploit/java/rmi/client/registry/builder'
|
||||||
|
require 'msf/core/exploit/java/rmi/client/registry/parser'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
# This mixin provides methods to simulate calls to the Java java/rmi/registry/RegistryImpl_Stub
|
||||||
|
# interface
|
||||||
|
module Registry
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder
|
||||||
|
include Msf::Exploit::Remote::Java::Rmi::Client::Registry::Parser
|
||||||
|
|
||||||
|
# Sends a Registry lookup call to the RMI endpoint. Simulates a call to the Java
|
||||||
|
# java/rmi/registry/RegistryImpl_Stub#lookup() method.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Hash, NilClass] The remote reference information if success, nil otherwise
|
||||||
|
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_registry_lookup
|
||||||
|
def send_registry_lookup(opts = {})
|
||||||
|
send_call(
|
||||||
|
sock: opts[:sock] || sock,
|
||||||
|
call: build_registry_lookup(opts)
|
||||||
|
)
|
||||||
|
|
||||||
|
return_value = recv_return(
|
||||||
|
sock: opts[:sock] || sock
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_value.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_value.is_exception?
|
||||||
|
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||||
|
end
|
||||||
|
|
||||||
|
remote_object = return_value.get_class_name
|
||||||
|
|
||||||
|
if remote_object.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
remote_location = parse_registry_lookup_endpoint(return_value)
|
||||||
|
|
||||||
|
if remote_location.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
remote_location.merge(object: remote_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sends a Registry list call to the RMI endpoint. Simulates a call to the Java
|
||||||
|
# java/rmi/registry/RegistryImpl_Stub#list() method
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [Rex::Socket::Tcp] :sock
|
||||||
|
# @return [Array, NilClass] The set of names if success, nil otherwise
|
||||||
|
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_registry_list
|
||||||
|
def send_registry_list(opts = {})
|
||||||
|
send_call(
|
||||||
|
sock: opts[:sock] || sock,
|
||||||
|
call: build_registry_list(opts)
|
||||||
|
)
|
||||||
|
|
||||||
|
return_value = recv_return(
|
||||||
|
sock: opts[:sock] || sock
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_value.nil?
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_value.is_exception?
|
||||||
|
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||||
|
end
|
||||||
|
|
||||||
|
names = parse_registry_list(return_value)
|
||||||
|
|
||||||
|
names
|
||||||
|
end
|
||||||
|
|
||||||
|
# Calculates the hash to make RMI calls for the
|
||||||
|
# java/rmi/registry/RegistryImpl_Stub interface
|
||||||
|
#
|
||||||
|
# @return [Fixnum] The interface's hash
|
||||||
|
def registry_interface_hash
|
||||||
|
hash = calculate_interface_hash(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'bind',
|
||||||
|
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
|
||||||
|
exceptions: ['java.rmi.AccessException', 'java.rmi.AlreadyBoundException', 'java.rmi.RemoteException']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'list',
|
||||||
|
descriptor: '()[Ljava/lang/String;',
|
||||||
|
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'lookup',
|
||||||
|
descriptor: '(Ljava/lang/String;)Ljava/rmi/Remote;',
|
||||||
|
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'rebind',
|
||||||
|
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
|
||||||
|
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'unbind',
|
||||||
|
descriptor: '(Ljava/lang/String;)V',
|
||||||
|
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,70 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Registry
|
||||||
|
module Builder
|
||||||
|
|
||||||
|
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#lookup() used to
|
||||||
|
# retrieve the remote reference bound to a name.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :name the name to lookup
|
||||||
|
# @return [Rex::Proto::Rmi::Model::Call]
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
|
||||||
|
def build_registry_lookup(opts = {})
|
||||||
|
object_number = opts[:object_number] || 0
|
||||||
|
uid_number = opts[:uid_number] || 0
|
||||||
|
uid_time = opts[:uid_time] || 0
|
||||||
|
uid_count = opts[:uid_count] || 0
|
||||||
|
name = opts[:name] || ''
|
||||||
|
|
||||||
|
call = build_call(
|
||||||
|
object_number: object_number,
|
||||||
|
uid_number: uid_number,
|
||||||
|
uid_time: uid_time,
|
||||||
|
uid_count: uid_count,
|
||||||
|
operation: 2, # java.rmi.Remote lookup(java.lang.String)
|
||||||
|
hash: registry_interface_hash,
|
||||||
|
arguments: [Rex::Java::Serialization::Model::Utf.new(nil, name)]
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#list() used to
|
||||||
|
# enumerate the names bound in a registry
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @return [Rex::Proto::Rmi::Model::Call]
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
|
||||||
|
def build_registry_list(opts = {})
|
||||||
|
object_number = opts[:object_number] || 0
|
||||||
|
uid_number = opts[:uid_number] || 0
|
||||||
|
uid_time = opts[:uid_time] || 0
|
||||||
|
uid_count = opts[:uid_count] || 0
|
||||||
|
|
||||||
|
call = build_call(
|
||||||
|
object_number: object_number,
|
||||||
|
uid_number: uid_number,
|
||||||
|
uid_time: uid_time,
|
||||||
|
uid_count: uid_count,
|
||||||
|
operation: 1, # java.lang.String list()[]
|
||||||
|
hash: registry_interface_hash,
|
||||||
|
arguments: []
|
||||||
|
)
|
||||||
|
|
||||||
|
call
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,53 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
module Java
|
||||||
|
module Rmi
|
||||||
|
module Client
|
||||||
|
module Registry
|
||||||
|
module Parser
|
||||||
|
# Parses a java/rmi/registry/RegistryImpl_Stub#lookup() return value to find out
|
||||||
|
# the remote reference information.
|
||||||
|
#
|
||||||
|
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
||||||
|
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
|
||||||
|
def parse_registry_lookup_endpoint(return_value)
|
||||||
|
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')
|
||||||
|
|
||||||
|
reference = extract_reference(return_io)
|
||||||
|
|
||||||
|
reference
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parses a java/rmi/registry/RegistryImpl_Stub#list() return value to find out
|
||||||
|
# the list of names registered.
|
||||||
|
#
|
||||||
|
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
||||||
|
# @return [Array, NilClass] The list of names registered if success, nil otherwise
|
||||||
|
def parse_registry_list(return_value)
|
||||||
|
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewArray)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
unless return_value.value[0].type == 'java.lang.String;'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return_value.value[0].values.collect { |val| val.contents }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,127 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
require 'rex/java/serialization'
|
||||||
|
require 'rex/text'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Exploit
|
||||||
|
class Remote
|
||||||
|
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
|
||||||
|
# @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)
|
||||||
|
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
|
||||||
|
m[: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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Extract an RMI interface reference from an IO
|
||||||
|
#
|
||||||
|
# @param io [IO] the io to extract the reference from, should contain the data
|
||||||
|
# inside a BlockData with the reference information.
|
||||||
|
# @return [Hash, nil] the extracted reference if success, nil otherwise
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Jmx:Server::Parser#parse_jmx_new_client_endpoint
|
||||||
|
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Parser#parse_registry_lookup_endpoint
|
||||||
|
def extract_reference(io)
|
||||||
|
ref = extract_string(io)
|
||||||
|
unless ref && ref == 'UnicastRef'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
address = extract_string(io)
|
||||||
|
return nil unless address
|
||||||
|
|
||||||
|
port = extract_int(io)
|
||||||
|
return nil unless port
|
||||||
|
|
||||||
|
object_number = extract_long(io)
|
||||||
|
|
||||||
|
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(io)
|
||||||
|
|
||||||
|
{address: address, port: port, object_number: object_number, uid: uid}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,96 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Builder
|
|
||||||
# Builds a RMI header stream
|
|
||||||
#
|
|
||||||
# @param opts [Hash{Symbol => <String, Fixnum>}]
|
|
||||||
# @option opts [String] :signature
|
|
||||||
# @option opts [Fixnum] :version
|
|
||||||
# @option opts [Fixnum] :protocol
|
|
||||||
# @return [Rex::Proto::Rmi::Model::OutputHeader]
|
|
||||||
def build_header(opts = {})
|
|
||||||
signature = opts[:signature] || Rex::Proto::Rmi::Model::SIGNATURE
|
|
||||||
version = opts[:version] || 2
|
|
||||||
protocol = opts[:protocol] || Rex::Proto::Rmi::Model::STREAM_PROTOCOL
|
|
||||||
|
|
||||||
header = Rex::Proto::Rmi::Model::OutputHeader.new(
|
|
||||||
signature: signature,
|
|
||||||
version: version,
|
|
||||||
protocol: protocol)
|
|
||||||
|
|
||||||
header
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds a RMI call stream
|
|
||||||
#
|
|
||||||
# @param opts [Hash{Symbol => <Fixnum, Array>}]
|
|
||||||
# @option opts [Fixnum] :message_id
|
|
||||||
# @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] :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
|
|
||||||
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
|
|
||||||
hash = opts[:hash] || 0
|
|
||||||
arguments = opts[:arguments] || []
|
|
||||||
|
|
||||||
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.new(
|
|
||||||
number: uid_number,
|
|
||||||
time: uid_time,
|
|
||||||
count: uid_count
|
|
||||||
)
|
|
||||||
|
|
||||||
call_data = Rex::Proto::Rmi::Model::CallData.new(
|
|
||||||
object_number: object_number,
|
|
||||||
uid: uid,
|
|
||||||
operation: operation,
|
|
||||||
hash: hash,
|
|
||||||
arguments: arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
call = Rex::Proto::Rmi::Model::Call.new(
|
|
||||||
message_id: message_id,
|
|
||||||
call_data: call_data
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds a RMI dgc ack stream
|
|
||||||
#
|
|
||||||
# @param opts [Hash{Symbol => <Fixnum, String>}]
|
|
||||||
# @option opts [Fixnum] :stream_id
|
|
||||||
# @option opts [String] :unique_identifier
|
|
||||||
# @return [Rex::Proto::Rmi::Model::DgcAck]
|
|
||||||
def build_dgc_ack(opts = {})
|
|
||||||
stream_id = opts[:stream_id] || Rex::Proto::Rmi::Model::DGC_ACK_MESSAGE
|
|
||||||
unique_identifier = opts[:unique_identifier] || "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
||||||
|
|
||||||
dgc_ack = Rex::Proto::Rmi::Model::DgcAck.new(
|
|
||||||
stream_id: stream_id,
|
|
||||||
unique_identifier: unique_identifier
|
|
||||||
)
|
|
||||||
|
|
||||||
dgc_ack
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,164 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
require 'rex/proto/rmi'
|
|
||||||
require 'rex/java/serialization'
|
|
||||||
require 'stringio'
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
|
|
||||||
require 'msf/java/rmi/util'
|
|
||||||
require 'msf/java/rmi/builder'
|
|
||||||
require 'msf/java/rmi/client/registry'
|
|
||||||
require 'msf/java/rmi/client/jmx'
|
|
||||||
|
|
||||||
include Msf::Java::Rmi::Util
|
|
||||||
include Msf::Java::Rmi::Builder
|
|
||||||
include Msf::Java::Rmi::Client::Registry
|
|
||||||
include Msf::Java::Rmi::Client::Jmx
|
|
||||||
include Exploit::Remote::Tcp
|
|
||||||
|
|
||||||
def initialize(info = {})
|
|
||||||
super
|
|
||||||
|
|
||||||
register_advanced_options(
|
|
||||||
[
|
|
||||||
OptInt.new('RmiReadLoopTimeout', [ true, 'Maximum number of seconds to wait for data between read iterations', 1])
|
|
||||||
], Msf::Java::Rmi::Client
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the timeout to wait for data between read iterations
|
|
||||||
#
|
|
||||||
# @return [Fixnum]
|
|
||||||
def read_loop_timeout
|
|
||||||
datastore['RmiReadLoopTimeout'] || 1
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the target host
|
|
||||||
#
|
|
||||||
# @return [String]
|
|
||||||
def rhost
|
|
||||||
datastore['RHOST']
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the target port
|
|
||||||
#
|
|
||||||
# @return [Fixnum]
|
|
||||||
def rport
|
|
||||||
datastore['RPORT']
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the RMI server peer
|
|
||||||
#
|
|
||||||
# @return [String]
|
|
||||||
def peer
|
|
||||||
"#{rhost}:#{rport}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sends a RMI header stream
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Fixnum] the number of bytes sent
|
|
||||||
# @see Msf::Rmi::Client::Streams#build_header
|
|
||||||
def send_header(opts = {})
|
|
||||||
nsock = opts[:sock] || sock
|
|
||||||
stream = build_header(opts)
|
|
||||||
nsock.put(stream.encode + "\x00\x00\x00\x00\x00\x00")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sends a RMI CALL stream
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @option opts [Rex::Proto::Rmi::Model::Call] :call
|
|
||||||
# @return [Fixnum] the number of bytes sent
|
|
||||||
# @see Msf::Rmi::Client::Streams#build_call
|
|
||||||
def send_call(opts = {})
|
|
||||||
nsock = opts[:sock] || sock
|
|
||||||
call = opts[:call] || build_call(opts)
|
|
||||||
nsock.put(call.encode)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sends a RMI DGCACK stream
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Fixnum] the number of bytes sent
|
|
||||||
# @see Msf::Rmi::Client::Streams#build_dgc_ack
|
|
||||||
def send_dgc_ack(opts = {})
|
|
||||||
nsock = opts[:sock] || sock
|
|
||||||
stream = build_dgc_ack(opts)
|
|
||||||
nsock.put(stream.encode)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Reads the Protocol Ack
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Rex::Proto::Rmi::Model::ProtocolAck] if success
|
|
||||||
# @return [NilClass] otherwise
|
|
||||||
# @see Rex::Proto::Rmi::Model::ProtocolAck.decode
|
|
||||||
def recv_protocol_ack(opts = {})
|
|
||||||
nsock = opts[:sock] || sock
|
|
||||||
data = safe_get_once(nsock)
|
|
||||||
begin
|
|
||||||
ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data))
|
|
||||||
rescue Rex::Proto::Rmi::DecodeError
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
ack
|
|
||||||
end
|
|
||||||
|
|
||||||
# Reads a ReturnData message and returns the java serialized stream
|
|
||||||
# with the return data value.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Rex::Proto::Rmi::Model::ReturnValue] if success
|
|
||||||
# @return [NilClass] otherwise
|
|
||||||
# @see Rex::Proto::Rmi::Model::ReturnData.decode
|
|
||||||
def recv_return(opts = {})
|
|
||||||
nsock = opts[:sock] || sock
|
|
||||||
data = safe_get_once(nsock)
|
|
||||||
|
|
||||||
begin
|
|
||||||
return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data))
|
|
||||||
rescue Rex::Proto::Rmi::DecodeError
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return_data.return_value
|
|
||||||
end
|
|
||||||
|
|
||||||
# Helper method to read fragmented data from a ```Rex::Socket::Tcp```
|
|
||||||
#
|
|
||||||
# @param nsock [Rex::Socket::Tcp]
|
|
||||||
# @return [String]
|
|
||||||
def safe_get_once(nsock = sock, loop_timeout = read_loop_timeout)
|
|
||||||
data = ''
|
|
||||||
begin
|
|
||||||
res = nsock.get_once
|
|
||||||
rescue ::EOFError
|
|
||||||
res = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
while res && nsock.has_read_data?(loop_timeout)
|
|
||||||
data << res
|
|
||||||
begin
|
|
||||||
res = nsock.get_once
|
|
||||||
rescue ::EOFError
|
|
||||||
res = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
data << res if res
|
|
||||||
data
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,23 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Jmx
|
|
||||||
require 'msf/java/rmi/client/jmx/server'
|
|
||||||
require 'msf/java/rmi/client/jmx/connection'
|
|
||||||
|
|
||||||
include Msf::Java::Rmi::Client::Jmx::Server
|
|
||||||
include Msf::Java::Rmi::Client::Jmx::Connection
|
|
||||||
|
|
||||||
OBJECT_NAME_UID = 1081892073854801359
|
|
||||||
BYTE_ARRAY_UID = -5984413125824719648
|
|
||||||
MARSHALLED_OBJECT_UID = 8988374069173025854
|
|
||||||
STRING_ARRAY_UID = -5921575005990323385
|
|
||||||
OBJECT_ARRAY_UID = -8012369246846506644
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,122 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Jmx
|
|
||||||
# This mixin provides methods to simulate calls to the Java
|
|
||||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub
|
|
||||||
# interface
|
|
||||||
module Connection
|
|
||||||
require 'msf/java/rmi/client/jmx/connection/builder'
|
|
||||||
|
|
||||||
include Msf::Java::Rmi::Client::Jmx::Connection::Builder
|
|
||||||
|
|
||||||
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
|
|
||||||
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
|
||||||
# method.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [TrueClass, NilClass] true if success, nil otherwise
|
|
||||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_get_object_instance
|
|
||||||
def send_jmx_get_object_instance(opts = {})
|
|
||||||
send_call(
|
|
||||||
sock: opts[:sock] || sock,
|
|
||||||
call: build_jmx_get_object_instance(opts)
|
|
||||||
)
|
|
||||||
|
|
||||||
return_value = recv_return(
|
|
||||||
sock: opts[:sock] || sock
|
|
||||||
)
|
|
||||||
|
|
||||||
if return_value.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_value.is_exception?
|
|
||||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
|
||||||
end
|
|
||||||
|
|
||||||
unless return_value.get_class_name == 'javax.management.ObjectInstance'
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sends a call to the JMXRMI endpoint to create an MBean instance. Simulates a call
|
|
||||||
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
|
||||||
# method.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [TrueClass, NilClass] true if success, nil otherwise
|
|
||||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_create_mbean
|
|
||||||
def send_jmx_create_mbean(opts = {})
|
|
||||||
send_call(
|
|
||||||
sock: opts[:sock] || sock,
|
|
||||||
call: build_jmx_create_mbean(opts)
|
|
||||||
)
|
|
||||||
|
|
||||||
return_value = recv_return(
|
|
||||||
sock: opts[:sock] || sock
|
|
||||||
)
|
|
||||||
|
|
||||||
if return_value.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_value.is_exception?
|
|
||||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
|
||||||
end
|
|
||||||
|
|
||||||
unless return_value.get_class_name == 'javax.management.ObjectInstance'
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sends a call to the JMXRMI endpoint to invoke an MBean method. Simulates a call
|
|
||||||
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
|
||||||
# method.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [TrueClass, NilClass] true if success, nil otherwise
|
|
||||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_invoke
|
|
||||||
def send_jmx_invoke(opts = {})
|
|
||||||
send_call(
|
|
||||||
sock: opts[:sock] || sock,
|
|
||||||
call: build_jmx_invoke(opts)
|
|
||||||
)
|
|
||||||
|
|
||||||
return_value = recv_return(
|
|
||||||
sock: opts[:sock] || sock
|
|
||||||
)
|
|
||||||
|
|
||||||
if return_value.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_value.is_exception?
|
|
||||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
|
||||||
end
|
|
||||||
|
|
||||||
unless return_value.get_class_name == 'java.util.HashSet'
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,234 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Jmx
|
|
||||||
module Connection
|
|
||||||
module Builder
|
|
||||||
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
|
||||||
# used to retrieve an MBean instance
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :name the MBean name
|
|
||||||
# @return [Rex::Proto::Rmi::Model::Call]
|
|
||||||
# @see Msf::Java::Rmi::Builder.build_call
|
|
||||||
def build_jmx_get_object_instance(opts = {})
|
|
||||||
object_number = opts[:object_number] || 0
|
|
||||||
uid_number = opts[:uid_number] || 0
|
|
||||||
uid_time = opts[:uid_time] || 0
|
|
||||||
uid_count = opts[:uid_count] || 0
|
|
||||||
name = opts[:name] || ''
|
|
||||||
|
|
||||||
arguments = build_jmx_get_object_instance_args(name)
|
|
||||||
|
|
||||||
method_hash = calculate_method_hash('getObjectInstance(Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
|
|
||||||
|
|
||||||
call = build_call(
|
|
||||||
object_number: object_number,
|
|
||||||
uid_number: uid_number,
|
|
||||||
uid_time: uid_time,
|
|
||||||
uid_count: uid_count,
|
|
||||||
operation: -1,
|
|
||||||
hash: method_hash,
|
|
||||||
arguments: arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds an an array of arguments o build a call to
|
|
||||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
|
||||||
#
|
|
||||||
# @param name [String] the MBean name
|
|
||||||
# @return [Array]
|
|
||||||
def build_jmx_get_object_instance_args(name = '')
|
|
||||||
builder = Rex::Java::Serialization::Builder.new
|
|
||||||
|
|
||||||
new_object = builder.new_object(
|
|
||||||
name: 'javax.management.ObjectName',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
|
|
||||||
flags: 3
|
|
||||||
)
|
|
||||||
|
|
||||||
arguments = [
|
|
||||||
new_object,
|
|
||||||
Rex::Java::Serialization::Model::Utf.new(nil, name),
|
|
||||||
Rex::Java::Serialization::Model::EndBlockData.new,
|
|
||||||
Rex::Java::Serialization::Model::NullReference.new
|
|
||||||
]
|
|
||||||
|
|
||||||
arguments
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
|
||||||
# used to retrieve an MBean instance
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :name the MBean name
|
|
||||||
# @return [Rex::Proto::Rmi::Model::Call]
|
|
||||||
# @see Msf::Java::Rmi::Builder.build_call
|
|
||||||
def build_jmx_create_mbean(opts = {})
|
|
||||||
name = opts[:name] || ''
|
|
||||||
object_number = opts[:object_number] || 0
|
|
||||||
uid_number = opts[:uid_number] || 0
|
|
||||||
uid_time = opts[:uid_time] || 0
|
|
||||||
uid_count = opts[:uid_count] || 0
|
|
||||||
|
|
||||||
method_hash = calculate_method_hash('createMBean(Ljava/lang/String;Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
|
|
||||||
|
|
||||||
arguments = build_jmx_create_mbean_args(name)
|
|
||||||
|
|
||||||
call = build_call(
|
|
||||||
object_number: object_number,
|
|
||||||
uid_number: uid_number,
|
|
||||||
uid_time: uid_time,
|
|
||||||
uid_count: uid_count,
|
|
||||||
operation: -1,
|
|
||||||
hash: method_hash,
|
|
||||||
arguments: arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds an an array of arguments o build a call to
|
|
||||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
|
||||||
#
|
|
||||||
# @param name [Hash] the MBean name
|
|
||||||
# @return [Array]
|
|
||||||
def build_jmx_create_mbean_args(name = '')
|
|
||||||
arguments = [
|
|
||||||
Rex::Java::Serialization::Model::Utf.new(nil, name),
|
|
||||||
Rex::Java::Serialization::Model::NullReference.new,
|
|
||||||
Rex::Java::Serialization::Model::NullReference.new
|
|
||||||
]
|
|
||||||
|
|
||||||
arguments
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
|
||||||
# used to invoke an MBean method
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :name the MBean name
|
|
||||||
# @return [Rex::Proto::Rmi::Model::Call]
|
|
||||||
# @see Msf::Java::Rmi::Builder.build_call
|
|
||||||
# @see #build_jmx_invoke_args
|
|
||||||
def build_jmx_invoke(opts = {})
|
|
||||||
object_number = opts[:object_number] || 0
|
|
||||||
uid_number = opts[:uid_number] || 0
|
|
||||||
uid_time = opts[:uid_time] || 0
|
|
||||||
uid_count = opts[:uid_count] || 0
|
|
||||||
|
|
||||||
method_hash = calculate_method_hash('invoke(Ljavax/management/ObjectName;Ljava/lang/String;Ljava/rmi/MarshalledObject;[Ljava/lang/String;Ljavax/security/auth/Subject;)Ljava/lang/Object;')
|
|
||||||
|
|
||||||
arguments = build_jmx_invoke_args(opts)
|
|
||||||
|
|
||||||
call = build_call(
|
|
||||||
object_number: object_number,
|
|
||||||
uid_number: uid_number,
|
|
||||||
uid_time: uid_time,
|
|
||||||
uid_count: uid_count,
|
|
||||||
operation: -1,
|
|
||||||
hash: method_hash,
|
|
||||||
arguments: arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds an an array of arguments o build a call to
|
|
||||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :object the MBean name
|
|
||||||
# @option opts [String] :method the method name
|
|
||||||
# @option opts [Hash] :args the method arguments
|
|
||||||
# @return [Array]
|
|
||||||
def build_jmx_invoke_args(opts = {})
|
|
||||||
object_name = opts[:object] || ''
|
|
||||||
method_name = opts[:method] || ''
|
|
||||||
args = opts[:args] || {}
|
|
||||||
|
|
||||||
builder = Rex::Java::Serialization::Builder.new
|
|
||||||
|
|
||||||
new_object = builder.new_object(
|
|
||||||
name: 'javax.management.ObjectName',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
|
|
||||||
flags: 3
|
|
||||||
)
|
|
||||||
|
|
||||||
data_binary = builder.new_array(
|
|
||||||
name: '[B',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::BYTE_ARRAY_UID, # serialVersionUID
|
|
||||||
values_type: 'byte',
|
|
||||||
values: build_invoke_arguments_obj_bytes(args).encode.unpack('C*')
|
|
||||||
)
|
|
||||||
|
|
||||||
marshall_object = builder.new_object(
|
|
||||||
name: 'java.rmi.MarshalledObject',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::MARSHALLED_OBJECT_UID, # serialVersionUID
|
|
||||||
fields: [
|
|
||||||
['int', 'hash'],
|
|
||||||
['array', 'locBytes', '[B'],
|
|
||||||
['array', 'objBytes', '[B']
|
|
||||||
],
|
|
||||||
data: [
|
|
||||||
["int", 1919492550],
|
|
||||||
Rex::Java::Serialization::Model::NullReference.new,
|
|
||||||
data_binary
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
new_array = builder.new_array(
|
|
||||||
name: '[Ljava.lang.String;',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
|
|
||||||
values_type: 'java.lang.String;',
|
|
||||||
values: args.keys.collect { |k| Rex::Java::Serialization::Model::Utf.new(nil, k) }
|
|
||||||
)
|
|
||||||
|
|
||||||
arguments = [
|
|
||||||
new_object,
|
|
||||||
Rex::Java::Serialization::Model::Utf.new(nil, object_name),
|
|
||||||
Rex::Java::Serialization::Model::EndBlockData.new,
|
|
||||||
Rex::Java::Serialization::Model::Utf.new(nil, method_name),
|
|
||||||
marshall_object,
|
|
||||||
new_array,
|
|
||||||
Rex::Java::Serialization::Model::NullReference.new
|
|
||||||
]
|
|
||||||
|
|
||||||
arguments
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds a Rex::Java::Serialization::Model::Stream with the arguments to
|
|
||||||
# simulate a call to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
|
||||||
# method.
|
|
||||||
#
|
|
||||||
# @param args [Hash] the arguments of the method to invoke
|
|
||||||
# @return [Rex::Java::Serialization::Model::Stream]
|
|
||||||
def build_invoke_arguments_obj_bytes(args = {})
|
|
||||||
builder = Rex::Java::Serialization::Builder.new
|
|
||||||
|
|
||||||
new_array = builder.new_array(
|
|
||||||
name: '[Ljava.lang.Object;',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_ARRAY_UID, # serialVersionUID
|
|
||||||
annotations: [Rex::Java::Serialization::Model::EndBlockData.new],
|
|
||||||
values_type: 'java.lang.Object;',
|
|
||||||
values: args.values.collect { |arg| Rex::Java::Serialization::Model::Utf.new(nil, arg) }
|
|
||||||
)
|
|
||||||
|
|
||||||
stream = Rex::Java::Serialization::Model::Stream.new
|
|
||||||
stream.contents << new_array
|
|
||||||
|
|
||||||
stream
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,57 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Jmx
|
|
||||||
module Server
|
|
||||||
require 'msf/java/rmi/client/jmx/server/builder'
|
|
||||||
require 'msf/java/rmi/client/jmx/server/parser'
|
|
||||||
|
|
||||||
include Msf::Java::Rmi::Client::Jmx::Server::Builder
|
|
||||||
include Msf::Java::Rmi::Client::Jmx::Server::Parser
|
|
||||||
|
|
||||||
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
|
|
||||||
# to the Java javax/management/remote/rmi/RMIServer_Stub#newClient()
|
|
||||||
# method.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Hash, NilClass] The connection information if success, nil otherwise
|
|
||||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_new_client
|
|
||||||
def send_new_client(opts = {})
|
|
||||||
send_call(
|
|
||||||
sock: opts[:sock] || sock,
|
|
||||||
call: build_jmx_new_client(opts)
|
|
||||||
)
|
|
||||||
|
|
||||||
return_value = recv_return(
|
|
||||||
sock: opts[:sock] || sock
|
|
||||||
)
|
|
||||||
|
|
||||||
if return_value.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_value.is_exception?
|
|
||||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
|
||||||
end
|
|
||||||
|
|
||||||
remote_object = return_value.get_class_name
|
|
||||||
|
|
||||||
unless remote_object && remote_object == 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
reference = parse_jmx_new_client_endpoint(return_value)
|
|
||||||
|
|
||||||
reference
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,73 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Jmx
|
|
||||||
module Server
|
|
||||||
module Builder
|
|
||||||
|
|
||||||
# Builds an RMI call to javax/management/remote/rmi/RMIServer_Stub#newClient()
|
|
||||||
# used to enumerate the names bound in a registry
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :username the JMX role to establish the connection if needed
|
|
||||||
# @option opts [String] :password the JMX password to establish the connection if needed
|
|
||||||
# @return [Rex::Proto::Rmi::Model::Call]
|
|
||||||
# @see Msf::Java::Rmi::Builder.build_call
|
|
||||||
def build_jmx_new_client(opts = {})
|
|
||||||
object_number = opts[:object_number] || 0
|
|
||||||
uid_number = opts[:uid_number] || 0
|
|
||||||
uid_time = opts[:uid_time] || 0
|
|
||||||
uid_count = opts[:uid_count] || 0
|
|
||||||
username = opts[:username]
|
|
||||||
password = opts[:password] || ''
|
|
||||||
|
|
||||||
if username
|
|
||||||
arguments = build_jmx_new_client_args(username, password)
|
|
||||||
else
|
|
||||||
arguments = [Rex::Java::Serialization::Model::NullReference.new]
|
|
||||||
end
|
|
||||||
|
|
||||||
call = build_call(
|
|
||||||
object_number: object_number,
|
|
||||||
uid_number: uid_number,
|
|
||||||
uid_time: uid_time,
|
|
||||||
uid_count: uid_count,
|
|
||||||
operation: -1,
|
|
||||||
hash: -1089742558549201240, # javax.management.remote.rmi.RMIServer.newClient
|
|
||||||
arguments: arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds a Rex::Java::Serialization::Model::NewArray with credentials
|
|
||||||
# to make an javax/management/remote/rmi/RMIServer_Stub#newClient call
|
|
||||||
#
|
|
||||||
# @param username [String] The username (role) to authenticate with
|
|
||||||
# @param password [String] The password to authenticate with
|
|
||||||
# @return [Array<Rex::Java::Serialization::Model::NewArray>]
|
|
||||||
def build_jmx_new_client_args(username = '', password = '')
|
|
||||||
builder = Rex::Java::Serialization::Builder.new
|
|
||||||
|
|
||||||
auth_array = builder.new_array(
|
|
||||||
name: '[Ljava.lang.String;',
|
|
||||||
serial: Msf::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
|
|
||||||
values_type: 'java.lang.String;',
|
|
||||||
values: [
|
|
||||||
Rex::Java::Serialization::Model::Utf.new(nil, username),
|
|
||||||
Rex::Java::Serialization::Model::Utf.new(nil, password)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
[auth_array]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,35 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Jmx
|
|
||||||
module Server
|
|
||||||
module Parser
|
|
||||||
# Parses a javax/management/remote/rmi/RMIServer_Stub#newClient() return value
|
|
||||||
# to find out the remote reference information.
|
|
||||||
#
|
|
||||||
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
|
||||||
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
|
|
||||||
def parse_jmx_new_client_endpoint(return_value)
|
|
||||||
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')
|
|
||||||
|
|
||||||
reference = extract_reference(return_io)
|
|
||||||
|
|
||||||
reference
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,129 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
# This mixin provides methods to simulate calls to the Java java/rmi/registry/RegistryImpl_Stub
|
|
||||||
# interface
|
|
||||||
module Registry
|
|
||||||
require 'msf/java/rmi/client/registry/builder'
|
|
||||||
require 'msf/java/rmi/client/registry/parser'
|
|
||||||
|
|
||||||
include Msf::Java::Rmi::Client::Registry::Builder
|
|
||||||
include Msf::Java::Rmi::Client::Registry::Parser
|
|
||||||
|
|
||||||
# Sends a Registry lookup call to the RMI endpoint. Simulates a call to the Java
|
|
||||||
# java/rmi/registry/RegistryImpl_Stub#lookup() method.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Hash, NilClass] The remote reference information if success, nil otherwise
|
|
||||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_registry_lookup
|
|
||||||
def send_registry_lookup(opts = {})
|
|
||||||
send_call(
|
|
||||||
sock: opts[:sock] || sock,
|
|
||||||
call: build_registry_lookup(opts)
|
|
||||||
)
|
|
||||||
|
|
||||||
return_value = recv_return(
|
|
||||||
sock: opts[:sock] || sock
|
|
||||||
)
|
|
||||||
|
|
||||||
if return_value.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_value.is_exception?
|
|
||||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
|
||||||
end
|
|
||||||
|
|
||||||
remote_object = return_value.get_class_name
|
|
||||||
|
|
||||||
if remote_object.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
remote_location = parse_registry_lookup_endpoint(return_value)
|
|
||||||
|
|
||||||
if remote_location.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
remote_location.merge(object: remote_object)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sends a Registry list call to the RMI endpoint. Simulates a call to the Java
|
|
||||||
# java/rmi/registry/RegistryImpl_Stub#list() method
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [Rex::Socket::Tcp] :sock
|
|
||||||
# @return [Array, NilClass] The set of names if success, nil otherwise
|
|
||||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_registry_list
|
|
||||||
def send_registry_list(opts = {})
|
|
||||||
send_call(
|
|
||||||
sock: opts[:sock] || sock,
|
|
||||||
call: build_registry_list(opts)
|
|
||||||
)
|
|
||||||
|
|
||||||
return_value = recv_return(
|
|
||||||
sock: opts[:sock] || sock
|
|
||||||
)
|
|
||||||
|
|
||||||
if return_value.nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_value.is_exception?
|
|
||||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
|
||||||
end
|
|
||||||
|
|
||||||
names = parse_registry_list(return_value)
|
|
||||||
|
|
||||||
names
|
|
||||||
end
|
|
||||||
|
|
||||||
# Calculates the hash to make RMI calls for the
|
|
||||||
# java/rmi/registry/RegistryImpl_Stub interface
|
|
||||||
#
|
|
||||||
# @return [Fixnum] The interface's hash
|
|
||||||
def registry_interface_hash
|
|
||||||
hash = calculate_interface_hash(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
name: 'bind',
|
|
||||||
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
|
|
||||||
exceptions: ['java.rmi.AccessException', 'java.rmi.AlreadyBoundException', 'java.rmi.RemoteException']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'list',
|
|
||||||
descriptor: '()[Ljava/lang/String;',
|
|
||||||
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'lookup',
|
|
||||||
descriptor: '(Ljava/lang/String;)Ljava/rmi/Remote;',
|
|
||||||
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'rebind',
|
|
||||||
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
|
|
||||||
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'unbind',
|
|
||||||
descriptor: '(Ljava/lang/String;)V',
|
|
||||||
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
hash
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,66 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Registry
|
|
||||||
module Builder
|
|
||||||
|
|
||||||
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#lookup() used to
|
|
||||||
# retrieve the remote reference bound to a name.
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :name the name to lookup
|
|
||||||
# @return [Rex::Proto::Rmi::Model::Call]
|
|
||||||
# @see Msf::Java::Rmi::Builder.build_call
|
|
||||||
def build_registry_lookup(opts = {})
|
|
||||||
object_number = opts[:object_number] || 0
|
|
||||||
uid_number = opts[:uid_number] || 0
|
|
||||||
uid_time = opts[:uid_time] || 0
|
|
||||||
uid_count = opts[:uid_count] || 0
|
|
||||||
name = opts[:name] || ''
|
|
||||||
|
|
||||||
call = build_call(
|
|
||||||
object_number: object_number,
|
|
||||||
uid_number: uid_number,
|
|
||||||
uid_time: uid_time,
|
|
||||||
uid_count: uid_count,
|
|
||||||
operation: 2, # java.rmi.Remote lookup(java.lang.String)
|
|
||||||
hash: registry_interface_hash,
|
|
||||||
arguments: [Rex::Java::Serialization::Model::Utf.new(nil, name)]
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
|
|
||||||
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#list() used to
|
|
||||||
# enumerate the names bound in a registry
|
|
||||||
#
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @return [Rex::Proto::Rmi::Model::Call]
|
|
||||||
# @see Msf::Java::Rmi::Builder.build_call
|
|
||||||
def build_registry_list(opts = {})
|
|
||||||
object_number = opts[:object_number] || 0
|
|
||||||
uid_number = opts[:uid_number] || 0
|
|
||||||
uid_time = opts[:uid_time] || 0
|
|
||||||
uid_count = opts[:uid_count] || 0
|
|
||||||
|
|
||||||
call = build_call(
|
|
||||||
object_number: object_number,
|
|
||||||
uid_number: uid_number,
|
|
||||||
uid_time: uid_time,
|
|
||||||
uid_count: uid_count,
|
|
||||||
operation: 1, # java.lang.String list()[]
|
|
||||||
hash: registry_interface_hash,
|
|
||||||
arguments: []
|
|
||||||
)
|
|
||||||
|
|
||||||
call
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,49 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
module Java
|
|
||||||
module Rmi
|
|
||||||
module Client
|
|
||||||
module Registry
|
|
||||||
module Parser
|
|
||||||
# Parses a java/rmi/registry/RegistryImpl_Stub#lookup() return value to find out
|
|
||||||
# the remote reference information.
|
|
||||||
#
|
|
||||||
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
|
||||||
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
|
|
||||||
def parse_registry_lookup_endpoint(return_value)
|
|
||||||
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')
|
|
||||||
|
|
||||||
reference = extract_reference(return_io)
|
|
||||||
|
|
||||||
reference
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parses a java/rmi/registry/RegistryImpl_Stub#list() return value to find out
|
|
||||||
# the list of names registered.
|
|
||||||
#
|
|
||||||
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
|
||||||
# @return [Array, NilClass] The list of names registered if success, nil otherwise
|
|
||||||
def parse_registry_list(return_value)
|
|
||||||
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewArray)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
unless return_value.value[0].type == 'java.lang.String;'
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return_value.value[0].values.collect { |val| val.contents }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,122 +0,0 @@
|
||||||
# -*- 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
|
|
||||||
# @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)
|
|
||||||
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
|
|
||||||
m[: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
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Extract an RMI interface reference from an IO
|
|
||||||
#
|
|
||||||
# @param io [IO] the io to extract the reference from, should contain the data
|
|
||||||
# inside a BlockData with the reference information.
|
|
||||||
# @return [Hash, nil] the extracted reference if success, nil otherwise
|
|
||||||
# @see Msf::Java::Rmi::Client::Jmx:Server::Parser#parse_jmx_new_client_endpoint
|
|
||||||
# @see Msf::Java::Rmi::Client::Registry::Parser#parse_registry_lookup_endpoint
|
|
||||||
def extract_reference(io)
|
|
||||||
ref = extract_string(io)
|
|
||||||
unless ref && ref == 'UnicastRef'
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
address = extract_string(io)
|
|
||||||
return nil unless address
|
|
||||||
|
|
||||||
port = extract_int(io)
|
|
||||||
return nil unless port
|
|
||||||
|
|
||||||
object_number = extract_long(io)
|
|
||||||
|
|
||||||
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(io)
|
|
||||||
|
|
||||||
{address: address, port: port, object_number: object_number, uid: uid}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -9,7 +9,7 @@ require 'rex/java/serialization'
|
||||||
class Metasploit3 < Msf::Auxiliary
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
include Msf::Auxiliary::Report
|
include Msf::Auxiliary::Report
|
||||||
include Msf::Java::Rmi::Client
|
include Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super(
|
super(
|
||||||
|
|
|
@ -8,7 +8,7 @@ require 'rex/java/serialization'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Auxiliary
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
include Msf::Java::Rmi::Client
|
include Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
include Msf::Auxiliary::Scanner
|
include Msf::Auxiliary::Scanner
|
||||||
include Msf::Auxiliary::Report
|
include Msf::Auxiliary::Report
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpServer
|
include Msf::Exploit::Remote::HttpServer
|
||||||
include Msf::Java::Rmi::Client
|
include Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
|
|
@ -8,7 +8,7 @@ require 'msf/core'
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Java::Rmi::Client
|
include Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
include Msf::Exploit::Remote::HttpServer
|
include Msf::Exploit::Remote::HttpServer
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
|
|
|
@ -3,12 +3,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/builder'
|
require 'msf/core/exploit/java/rmi/builder'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Builder do
|
describe Msf::Exploit::Remote::Java::Rmi::Builder do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Builder
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Builder
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -4,12 +4,12 @@ require 'spec_helper'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Jmx::Connection::Builder do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Connection::Builder do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,10 +3,10 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Jmx::Connection do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Connection do
|
||||||
|
|
||||||
let(:name_get) { 'DefaultDomain:type=MLet' }
|
let(:name_get) { 'DefaultDomain:type=MLet' }
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ describe Msf::Java::Rmi::Client::Jmx::Connection do
|
||||||
|
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -4,12 +4,12 @@ require 'spec_helper'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Jmx::Server::Builder do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server::Builder do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,12 +3,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Jmx::Server::Parser do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server::Parser do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,10 +3,10 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Jmx::Server do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server do
|
||||||
|
|
||||||
let(:new_client_response) do
|
let(:new_client_response) do
|
||||||
"\x51\xac\xed\x00\x05\x77\x0f\x01\x82\x73\x92\x35\x00\x00\x01\x4c" +
|
"\x51\xac\xed\x00\x05\x77\x0f\x01\x82\x73\x92\x35\x00\x00\x01\x4c" +
|
||||||
|
@ -32,7 +32,7 @@ describe Msf::Java::Rmi::Client::Jmx::Server do
|
||||||
|
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,12 +3,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
describe ::Msf::Java::Rmi::Client::Registry::Builder do
|
describe ::Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,12 +3,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Registry::Parser do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Registry::Parser do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,10 +3,10 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client::Registry do
|
describe Msf::Exploit::Remote::Java::Rmi::Client::Registry do
|
||||||
|
|
||||||
let(:list_with_names_response) do
|
let(:list_with_names_response) do
|
||||||
"\x51\xac\xed\x00\x05\x77\x0f\x01\x82\x73\x92\x35\x00\x00\x01\x4c" +
|
"\x51\xac\xed\x00\x05\x77\x0f\x01\x82\x73\x92\x35\x00\x00\x01\x4c" +
|
||||||
|
@ -144,7 +144,7 @@ describe Msf::Java::Rmi::Client::Registry do
|
||||||
|
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -3,12 +3,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'rex/proto/rmi'
|
require 'rex/proto/rmi'
|
||||||
require 'msf/java/rmi/client'
|
require 'msf/core/exploit/java/rmi/client'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Client do
|
describe Msf::Exploit::Remote::Java::Rmi::Client do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Client
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Client
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
|
@ -2,12 +2,12 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
require 'rex/java/serialization'
|
require 'rex/java/serialization'
|
||||||
require 'msf/java/rmi/util'
|
require 'msf/core/exploit/java/rmi/util'
|
||||||
|
|
||||||
describe Msf::Java::Rmi::Util do
|
describe Msf::Exploit::Remote::Java::Rmi::Util do
|
||||||
subject(:mod) do
|
subject(:mod) do
|
||||||
mod = ::Msf::Exploit.new
|
mod = ::Msf::Exploit.new
|
||||||
mod.extend ::Msf::Java::Rmi::Util
|
mod.extend ::Msf::Exploit::Remote::Java::Rmi::Util
|
||||||
mod.send(:initialize)
|
mod.send(:initialize)
|
||||||
mod
|
mod
|
||||||
end
|
end
|
Loading…
Reference in New Issue