Bashed is an easy-rated Linux machine on the reputable penetration testing platform known as HackTheBox. The ultimate goal is to compromise this machine and gain root privileged access. In the write-up below I explain the steps I took to successfully gain root access to this machine. This one falls in the category of TJNull’s HackTheBox OSCP-like machines. So if you’re planning on taking the OSCP like me, this machine is good practice. The whole list of OSCP-like machines can be found here.
Reconnaissance
Those familiar with the Cyber Kill Chain are aware that reconnaissance is the first step in the process of compromising a system, so let’s start with that!
Discovering with Autorecon:
sudo python3 autorecon.py 10.10.10.68
Listed above are the results of a full TCP nmap scan. As we can see 65534 ports are closed, which means there’s only a single port open, in this case that’s port 80. We can immediately see that the HTTP-server-header is leaking service information and that there’s some sort of development website running. With the leaked service information in the back of our minds let’s investigate further by accessing the website.
Reading the contents of the webpage we see some information displayed about “phpbash”. After some searching I found a Github project, from which I concluded that it was a simple PHP web shell. Reading the paragraph under the title we can see that the author states this exact web shell is located somewhere on the server. The tool I usually prefer for finding hidden files on web servers is gobuster, let’s give that a try!
Dorking for hidden files using gobuster:
gobuster dir -u http://bashed.htb/ -w /opt/Seclists/Discovery/Web-Content/raft-large-directories.txt -t 30 -s 200,301 -o dirs/root-dirs.txt
/about.html (Status: 200) [Size: 8190]
/config.php (Status: 200) [Size: 0]
/contact.html (Status: 200) [Size: 7802]
/css (Status: 301) [Size: 308]
/dev (Status: 301) [Size: 308]
/fonts (Status: 301) [Size: 310]
/images (Status: 301) [Size: 311]
/index.html (Status: 200) [Size: 7742]
/index.html (Status: 200) [Size: 7742]
/js (Status: 301) [Size: 307]
/php (Status: 301) [Size: 308]
/server-status (Status: 403) [Size: 299]
/single.html (Status: 200) [Size: 7476]
/uploads (Status: 301) [Size: 312]
Listed above are the results of the gobuster scan, we immediately stumble upon some interesting directories such as dev, php and uploads. Let’s take a look at the dev directory first, since it’s the first of the three in the list.
Seems like there are two .php files in this directory, let’s check them out.
Navigating to both phpbash.min.php and phpbash.php we can confirm that we’ve found the exposed web shell. As illustrated above it’s possible to run commands, as the developer on Github explained it’s a semi-interactive web shell. So what can we do with this? First of all we can try to see if we can ping to our own machine. For this purpose I set up tcpdump on my own machine and then try pinging to it.
We conclude that outgoing connections aren’t blocked by some sort of firewall that’s running on the remote host. It’s always good practice to confirm this before trying to set up a reverse shell to your own machine. As we remember, this shell is only semi-interactive. This means that we can’t do basic things such as switching user. Because I didn’t want to be restricted I wanted to set up a reverse shell to my own machine. Let’s first check to see if we have wget available on the remote host.
With a simple “which” we can confirm that wget is installed on the remote host, thus we have the possibility to transfer files from our own machine to the Bashed machine. First, we have to check if we have write permissions to any folders in /var/www. After a quick directory listing we conclude that we only have read, write and execute permissions on the uploads folder.
Our prerequisites of uploading and triggering a PHP reverse shell have been met. Let’s utilize this by transferring a reverse shell to the Bashed machine using wget and on our own machine we spin up a quick web server using the Python module SimpleHTTPServer, hosting our reverse shell.
In the above image we can see that the shell has been transferred successfully, we confirm this by doing a directory listing of the contents in the uploads folder. Now all that’s left to do is to set up a listener on our own machine and to trigger the reverse shell. We do this by navigating to http://bashed.htb/uploads/dont-hijack-my-shell.php.
We caught the shell, this means we’re now no longer limited to a restricted shell, awesome! Before we continue, let’s do some housekeeping by improving our shell to use functions such as tab-autocomplete and clearing the screen. Let’s first set the environment variable TERM to the value of the variable on our own machine, this let’s us clear the screen.
Great success! We can now clear our screen. Now let’s enable tab-autocomplete. We do this by backgrounding our session using CTRL+Z, then type stty raw -echo, and lastly type fg + [double enter] to return to the session. The last thing to do is to spawn a fully interactive shell using Python, before that, let’s first confirm which Python version is running on Bashed.
Apparently we have both Python 2 and Python 3 running so we can improve our shell to a fully interactive TTY by spawning Bash utilizing either Python 2 or Python 3.
Now that our housekeeping is done, let’s continue to root. Usually, before I run automated privilege escalation scripts such as LinPEAS I’d like to do some manual enumeration to find any low hanging fruits. First, I always check which users can log in to the box. This way I can determine which users to look out for. From the command given below we conclude that three users on the box have a shell: root, arrexel and scriptmanager.
One command I always like to run after checking for users is sudo -l, this lists out commands that the logged-in user is allowed to run as another user. These commands are defined in something called sudo-snippets. Running the sudo -l command, we are presented with the following output.
The above output tells us that we’re allowed to run basically any command as scriptmanager without the system prompting us for a password. Since we don’t have any password of the scriptmanager user let’s just spawn a shell as scriptmanager.
Nice, we have now switched to the scriptmanager user! Browsing around the file system a bit we realize that we can also access arrexel’s home directory, which contains the user flag.
Right, now that we have user, let’s get root! Again, just browsing through the file system I notice there’s a scripts directory belonging to the scriptmanager user at the root of the file system, which is very interesting. Let’s check out this directory. Listing out the directory, we are presented with the following contents:
What do we see here? Well first of all we see a Python file that belongs to the scriptmanager user, which we have read and write permissions to. Second of all we see a test.txt file that is owned by the root user. Let’s check out both files. Opening both files we find that test.py writes out some contents to test.txt which is owned by root. We can really easily abuse this to get root access to the system. We simply transfer over a reverse shell in a file called test.py and delete the original test.py so our malicious script gets executed instead. Because the file is owned by root, our malicious script will get executed as the root user.
Illustrated above is a simple Python reverse shell which connects back to my IP-address on port 1234 and spawns a /bin/sh session. For all your reverse shells navigate to pentestmonkey. Let’s transfer our file using wget and Python SimpleHTTPServer again.
Now that our file is transferred let’s set-up a listener and wait until Cron runs the file and connects back to us. After a short while we receive a connection back.
We now have a shell as root, so that wraps up Bashed! Although this machine was quite easy, the techniques used were still very fun in my opinion. I hope you enjoyed this blog post, I hope to see you in the next one.