lib/msf/core/exploit/remote/java/rmi/util.rb
# -*- 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 [Integer] 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 [Integer] 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 [Integer, 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 byte from an IO
#
# @param io [IO] the io to extract the byte from
# @return [Byte, nil] the extracted byte if success, nil otherwise
def extract_byte(io)
byte_raw = io.read(1)
unless byte_raw && byte_raw.length == 1
return nil
end
byte = byte_raw.unpack('C')[0]
byte
end
# Extracts a long from an IO
#
# @param io [IO] the io to extract the long from
# @return [Integer, 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' || ref == 'UnicastRef2')
return nil
end
if ref == 'UnicastRef2'
form = extract_byte(io)
unless form == 0 || form == 1 # FORMAT_HOST_PORT or FORMAT_HOST_PORT_FACTORY
return nil
end
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
# Register ports and services for autofilter support
#
def register_common_rmi_ports_and_services
register_autofilter_ports([
999, 1090, 1098, 1099, 1100, 1101, 1102, 1103, 1129, 1030, 1035, 1199, 1234, 1440, 3273, 3333, 3900,
2199, 2809, 5520, 5580, 5521, 5999, 6060, 6789, 6996, 7700, 7800, 7878, 7890, 7801, 8050, 8051, 8085,
8091, 8205, 8303, 8642, 8701, 8686, 8888, 8889, 8890, 8901, 8902, 8903, 8999, 9001, 9003, 9004, 9005,
9050, 9090, 9099, 9300, 9500, 9711, 9809, 9810, 9811, 9812, 9813, 9814, 9815, 9875, 9910, 9991, 9999,
10001, 10162, 10098, 10099, 11001, 11099, 11333, 12000, 13013, 14000, 15000, 15001, 15200, 16000,
17200, 18980, 20000, 23791, 26256, 31099, 33000, 32913, 37718, 45230, 47001, 47002, 50050, 50500,
50501, 50502, 50503, 50504
])
register_autofilter_services(%W{ rmi rmid java-rmi rmiregistry })
end
end
end
end
end
end
end