metasploit-framework/modules/auxiliary/scanner/misc/java_rmi_server.rb

156 lines
5.6 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex/java/serialization'
class Metasploit3 < Msf::Auxiliary
include Msf::Java::Rmi::Client
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize
super(
'Name' => 'Java RMI Server Insecure Endpoint Code Execution Scanner',
'Description' => 'Detect Java RMI endpoints',
'Author' => ['mihi', 'hdm'],
'License' => MSF_LICENSE,
'References' =>
[
# RMI protocol specification
[ 'URL', 'http://download.oracle.com/javase/1.3/docs/guide/rmi/spec/rmi-protocol.html'],
# Placeholder reference for matching
[ 'MSF', 'java_rmi_server']
],
'DisclosureDate' => 'Oct 15 2011'
)
register_options(
[
Opt::RPORT(1099)
], self.class)
end
def run_host(target_host)
vprint_status("#{peer} - Sending RMI Header...")
connect
send_header
ack = recv_protocol_ack
if ack.nil?
print_error("#{peer} - Filed to negotiate RMI protocol")
disconnect
return
end
# Determine if the instance allows remote class loading
vprint_status("#{peer} - Sending RMI Call...")
jar = Rex::Text.rand_text_alpha(rand(8)+1) + '.jar'
jar_url = "file:RMIClassLoaderSecurityTest/" + jar
send_call(call_data: build_gc_call_data(jar_url))
return_data = recv_return
if return_data.nil?
print_error("#{peer} - Failed to send RMI Call, anyway JAVA RMI Endpoint detected")
report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "")
return
end
if loader_enabled?(return_data)
print_good("#{rhost}:#{rport} Java RMI Endpoint Detected: Class Loader Enabled")
svc = report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "Class Loader: Enabled")
report_vuln(
:host => rhost,
:service => svc,
:name => self.name,
:info => "Module #{self.fullname} confirmed remote code execution via this RMI service",
:refs => self.references
)
else
print_status("#{rhost}:#{rport} Java RMI Endpoint Detected: Class Loader Disabled")
report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "Class Loader: Disabled")
end
end
def loader_enabled?(stream)
stream.contents.each do |content|
if content.class == Rex::Java::Serialization::Model::NewObject &&
content.class_desc.description.class == Rex::Java::Serialization::Model::NewClassDesc &&
content.class_desc.description.class_name.contents == 'java.lang.ClassNotFoundException'&&
content.class_data[0].class == Rex::Java::Serialization::Model::NullReference &&
!content.class_data[1].contents.include?('RMI class loader disabled')
return true
end
end
false
end
def build_gc_call_data(jar_url)
stream = Rex::Java::Serialization::Model::Stream.new
block_data = Rex::Java::Serialization::Model::BlockData.new
block_data.contents = "\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xb6\x89\x8d\x8b\xf2\x86\x43"
block_data.length = block_data.contents.length
stream.contents << block_data
new_array_annotation = Rex::Java::Serialization::Model::Annotation.new
new_array_annotation.contents = [
Rex::Java::Serialization::Model::NullReference.new,
Rex::Java::Serialization::Model::EndBlockData.new
]
new_array_super = Rex::Java::Serialization::Model::ClassDesc.new
new_array_super.description = Rex::Java::Serialization::Model::NullReference.new
new_array_desc = Rex::Java::Serialization::Model::NewClassDesc.new
new_array_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.rmi.server.ObjID;')
new_array_desc.serial_version = 0x871300b8d02c647e
new_array_desc.flags = 2
new_array_desc.fields = []
new_array_desc.class_annotation = new_array_annotation
new_array_desc.super_class = new_array_super
array_desc = Rex::Java::Serialization::Model::ClassDesc.new
array_desc.description = new_array_desc
new_array = Rex::Java::Serialization::Model::NewArray.new
new_array.type = 'java.rmi.server.ObjID;'
new_array.values = []
new_array.array_description = array_desc
stream.contents << new_array
stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00")
new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new
new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'metasploit.RMILoader')
new_class_desc.serial_version = 0xa16544ba26f9c2f4
new_class_desc.flags = 2
new_class_desc.fields = []
new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new
new_class_desc.class_annotation.contents = [
Rex::Java::Serialization::Model::Utf.new(nil, jar_url),
Rex::Java::Serialization::Model::EndBlockData.new
]
new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new
new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new
new_object = Rex::Java::Serialization::Model::NewObject.new
new_object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new
new_object.class_desc.description = new_class_desc
new_object.class_data = []
stream.contents << new_object
stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00")
stream
end
end