Note: This is my first HTB writeup, so opinions are more than welcome.
Jarvis just retired today. Even though this is a medium box, I learned a lot from solving it, especially about systemctl and how I can abuse it to gain root privileges. Its IP address is 10.10.10.143 and I added it to /etc/hosts as jarvis.htb to make accessing the machine easier. Without further ado, let’s jump right in!
Scanning & Web App Enumeration
I always make a quick ‘light’ scan with nmap so I can get to work quickly and a full one to see if there are any uncommon open ports. In this case, the ligh one was enough to get the initial foothold:
OpenSSH seemed to be up-to-date, so I decided to check port 80 for vulnerabilities.
The site looked like it was custom-made, so I decided to explore it more. After playing around for a bit, I discovered an interesting URL:
Do you see the LFI? I did, too, but it turns out that was an SQL injection 🙂 A simple, working payload could be
I wanted to do the SQL injection manually, so I started ‘exhaustively searching’ for the number of columns. The SELECT statement worked with 7 entries, so the table probably had the same number of columns:
Now that we have a working SQL SELECT statement, we can insert anything in the results. I wanted to write a simple PHP shell in a file on the server and then use it to get a reverse shell. I tried writing using the INTO OUTFILE statement, and it worked. Also, since the target is most probably running Linux, I tried to write the file in the default webroot directory (/var/www/html):
There was no output, which is normal because the SQL engine saves the query output to a file instead of passing it on to PHP. We can test that the query worked by trying to run a simple command on the server (whoami):
One thing that I learned from the OSCP course is to only value reverse shells, so I spawned one using netcat:
It’s also a good idea to upgrade the shell to a tty:
Once I had a shell, I starter enumerating the machine. One thing that seemed odd was the sudo permission:
The www-data user is allowed to run /var/www/Admin-Utilities/simpler.py as pepper without providing any password. I thought this might be the path to privesc, and I was right! I first tried to read the source code of the script:
What caught my attention was the exec_ping function, because it uses os.system() to call ping, which is VERY unsafe:
The function is called when the program is being run with the -p switch. This means that we can execute any command given that we bypass the filter (our payload shouldn’t contains any character present in the forbidden array).
My solution was pretty straightforward, but I’m not sure it was the intended one. We can use $(command) to execute a command, however, I found it easier to store the command into a file and execute it as a script, as / is not a blacklisted character.
The program hangs because the script needs to terminate before the ping command is executed. A reverse shell connected on port 444, so I added my SSH public key in the ~/.ssh/authorized_keys file and connected using SSH:
We got user! I won’t display the file’s contents, but I can tell you that the proof starts with 2a 🙂
After getting the user flag, I started enumerating the machine again. While listing the SUID binaries, I noticed systemctl on the list:
This is odd because systemctl should be ran as the current user only. Instead, we can run it as its owner, root:
systemctl is used to turn Linux services on and off. The basic idea of exploitation is to create a new service (which is just a file, as you’ll see in a moment) and start it. Because systemctl is running as root, the service will be started as root.
Note: I didn’t come up with this method myself; I found it ongtfobins.
First, I created a service file using the following commands:
I reused the /tmp/yakuhito.sh script, because I was now controlling the box via an SSH session and port 444 wasn’t used anymore. The next step was to enable (or install) the service:
The shell hung and a reverse shell connected on port 444.
Again, I will not put the entire flag here, but I will tell you that it starts with d4 😉