Files
metasploit-gs/modules/auxiliary/scanner/misc/java_rmi_server.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

186 lines
6.6 KiB
Ruby
Raw Normal View History

2012-04-25 11:24:28 -05:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-04-25 11:24:28 -05:00
##
2015-01-07 19:06:09 -06:00
require 'rex/java/serialization'
2012-04-25 11:24:28 -05:00
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Java::Rmi::Client
2012-04-25 11:24:28 -05:00
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
2013-08-30 16:28:54 -05:00
2012-04-25 11:24:28 -05:00
def initialize
super(
'Name' => 'Java RMI Server Insecure Endpoint Code Execution Scanner',
2012-04-25 12:09:23 -05:00
'Description' => 'Detect Java RMI endpoints',
2012-05-02 22:53:24 -05:00
'Author' => ['mihi', 'hdm'],
2012-04-25 11:24:28 -05:00
'License' => MSF_LICENSE,
'References' =>
[
# RMI protocol specification
[ 'URL', 'http://download.oracle.com/javase/1.3/docs/guide/rmi/spec/rmi-protocol.html'],
2017-06-02 12:59:48 -05:00
[ 'URL', 'http://www.securitytracker.com/id?1026215'],
[ 'CVE', '2011-3556']
2012-04-25 11:24:28 -05:00
],
2012-04-25 15:54:42 -05:00
'DisclosureDate' => 'Oct 15 2011'
2012-04-25 11:24:28 -05:00
)
2013-08-30 16:28:54 -05:00
2012-04-25 11:24:28 -05:00
register_options(
[
2012-04-25 15:54:42 -05:00
Opt::RPORT(1099)
])
2012-04-25 11:24:28 -05:00
end
2013-08-30 16:28:54 -05:00
2012-04-25 11:24:28 -05:00
def run_host(target_host)
begin
connect
rescue Rex::ConnectionError
return Exploit::CheckCode::Unknown
end
2015-01-08 15:46:24 -06:00
vprint_status("Sending RMI Header...")
2015-01-08 15:46:24 -06:00
send_header
ack = recv_protocol_ack
if ack.nil?
2016-02-01 16:06:34 -06:00
print_error("Failed to negotiate RMI protocol")
disconnect
return Exploit::CheckCode::Unknown
2015-01-07 19:06:09 -06:00
end
2013-08-30 16:28:54 -05:00
2015-01-07 19:06:09 -06:00
# Determine if the instance allows remote class loading
2016-02-01 16:06:34 -06:00
vprint_status("Sending RMI Call...")
2015-01-08 14:01:04 -06:00
jar = Rex::Text.rand_text_alpha(rand(8)+1) + '.jar'
jar_url = "file:RMIClassLoaderSecurityTest/" + jar
2015-01-08 15:46:24 -06:00
dgc_interface_hash = calculate_interface_hash(
2015-03-16 23:44:16 -05:00
[
{
name: 'clean',
descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/VMID;Z)V',
exceptions: ['java.rmi.RemoteException']
},
{
name: 'dirty',
descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/Lease;)Ljava/rmi/dgc/Lease;',
exceptions: ['java.rmi.RemoteException']
}
]
)
2015-03-16 23:44:16 -05:00
# JDK 1.1 stub protocol
# Interface hash: 0xf6b6898d8bf28643 (sun.rmi.transport.DGCImpl_Stub)
# Operation: 0 (public void clean(ObjID[] paramArrayOfObjID, long paramLong, VMID paramVMID, boolean paramBoolean))
send_call(
object_number: 2,
uid_number: 0,
uid_time: 0,
uid_count: 0,
operation: 0,
2015-03-17 14:18:07 -05:00
hash: dgc_interface_hash,
2015-03-16 23:44:16 -05:00
arguments: build_dgc_clean_args(jar_url)
)
2015-03-17 21:29:52 -05:00
return_value = recv_return
2015-01-08 15:46:24 -06:00
2015-03-17 21:29:52 -05:00
if return_value.nil?
print_good("Failed to send RMI Call, anyway JAVA RMI Endpoint detected")
report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "")
return Exploit::CheckCode::Detected
2015-01-07 19:06:09 -06:00
end
2015-03-17 21:29:52 -05:00
if return_value.is_exception? && loader_enabled?(return_value.value)
2015-01-07 19:06:09 -06:00
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
)
Exploit::CheckCode::Vulnerable
2015-01-07 19:06:09 -06:00
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")
Exploit::CheckCode::Safe
2012-04-25 11:24:28 -05:00
end
end
2015-03-17 21:29:52 -05:00
def loader_enabled?(exception_stack)
exception_stack.each do |exception|
if exception.class == Rex::Java::Serialization::Model::NewObject &&
exception.class_desc.description.class == Rex::Java::Serialization::Model::NewClassDesc &&
exception.class_desc.description.class_name.contents == 'java.lang.ClassNotFoundException'&&
2015-10-09 11:05:05 -05:00
[Rex::Java::Serialization::Model::NullReference, Rex::Java::Serialization::Model::Reference].include?(exception.class_data[0].class) &&
2015-03-17 21:29:52 -05:00
!exception.class_data[1].contents.include?('RMI class loader disabled')
return true
end
end
false
2012-04-25 11:24:28 -05:00
end
2013-08-30 16:28:54 -05:00
2015-03-16 23:44:16 -05:00
# class: sun.rmi.trasnport.DGC
# method: public void clean(ObjID[] paramArrayOfObjID, long paramLong, VMID paramVMID, boolean paramBoolean)
def build_dgc_clean_args(jar_url)
arguments = []
2015-01-14 16:47:28 -06:00
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
2015-03-16 23:44:16 -05:00
# ObjID[] paramArrayOfObjID
arguments << new_array
# long paramLong
arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00")
2015-01-14 16:47:28 -06:00
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 = []
2015-03-16 23:44:16 -05:00
# VMID paramVMID
arguments << new_object
2015-01-14 16:47:28 -06:00
2015-03-16 23:44:16 -05:00
# boolean paramBoolean
arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00")
2015-01-14 16:47:28 -06:00
2015-03-16 23:44:16 -05:00
arguments
2015-01-14 16:47:28 -06:00
end
2012-04-25 11:24:28 -05:00
end