Sur cette machine Linux, nous allons exploiter une CVE en Javascript, cracker un mots de passe et exploiter une comparaison de chaînes de caractères défectueuse dans un script pour élever nos privilèges.
Scan Nmap
Nous commençons par une énumération à l’aide de nmap pour analyser notre cible :
- Le port 22 (SSH) est ouvert à l’aide d’OpenSSH 8.9
- Le port 80 (HTTP) héberge un site web fonctionnant sous Apache httpd 2.4.52 et il existe un hôte virtuel pour le domaine codify.htb.
- Le port 3000 (HTTP) héberge également un site web utilisant Node.js
Nous devons ajouter le domaine à notre fichier /etc/hosts :
Nous pouvons désormais naviguer sur http://codify.htb. Le port 3000 nous donne accès à l’application NodeJS, qui semble comporter deux pages. L’une est une sorte de bac à sable où nous pouvons exécuter du code Javascript, l’autre est la page « À propos de nous ». Au cours de notre exploration de la section « À propos de nous », nous trouvons une mention de vm2 et de la version précise utilisée (3.9.16), qui est vulnérable à la CVE-2023-29199.
Accès initial
Comme nous connaissons la CVE, nous pouvons nous renseigner à son sujet et trouver un PoC. J’ai trouvé celui-ci qui devrait nous permettre d’obtenir un RCE sur la cible. Après avoir lu le code, il semble que le PoC crée une fonction récursive qui génère une erreur. Au moment de catch l’exception, il accède à l’objet global process de NodeJS. Il peut donc importer child_process et exécuter une commande sur l’hôte distant.
Tout d’abord, assurons-nous qu’il fonctionne, nous pouvons lancer un serveur local sur notre machine fonctionnant sur le port 80, puis nous utilisons le PoC pour essayer d’exécuter une requête vers nous à l’aide d’une commande curl
Et ça marche, nous avons reçu une requête de notre cible.
L’étape suivante consiste à essayer d’obtenir un shell. Nous créons donc un payload encodé en base64, car nous voulons éviter d’avoir à gérer des caractères spéciaux :
Maintenant, nous pouvons lancer de nouveau notre PoC, mais en utilisant notre payload :
Et nous obtenons notre shell sur la cible :
Nous pouvons mettre à niveau notre shell et commencer notre énumération afin de trouver un moyen d’élever nos privilèges.
Élévation de privilèges
Énumération
Nous avons obtenu un shell en tant que “svc“, qui est un utilisateur ayant des privilèges limités, notre objectif est désormais de trouver un moyen d’élever nos privilèges. Nous commençons par consulter le fichier /etc/passwd et découvrons un autre utilisateur nommé Joshua.
Cet utilisateur pourrait être notre utilisateur permettant un mouvement latéral, alors gardons cette information à l’esprit pendant que nous explorons le système. Dans le dossier /var/www/contact/, nous trouvons un fichier de base de données nommé tickets.db.
Le fichier contient un hash pour l’utilisateur Joshua commençant par “$2a$“, ce qui indique probablement un algorithme bcrypt.
Cassage du mot de passe
Nous pouvons essayer de le cracker à l’aide de l’outil John the Ripper et l’utiliser pour effectuer un mouvement latéral si nous réussissons.
Nous venons d’obtenir le mot de passe de Joshua, nous pouvons maintenant essayer de nous connecter à sa place, cela fonctionne peut-être avec les mêmes identifiants.
Mouvement latéral
Très bien, nous pouvons désormais nous connecter à la machine via SSH en tant que joshua et essayer la commande sudo -l, puisque nous disposons du mot de passe correspondant. Le résultat nous indique que nous ne pouvons exécuter qu’une seule commande en utilisant les privilèges sudo :
Cela nous a conduit à un script bash permettant de sauvegarder certaines bases de données à l’aide du chemin /opt/scripts/mysql-backup.sh, qui semble intéressant. Jetons un œil au script et à ses permissions.
Nous n’avons pas le droit de modifier le script et il ne semble pas que nous puissions utiliser quelque chose comme le détournement binaire ou de chemin d’accès. Nous ne pouvons pas non plus accéder au fichier /root/.creds, nous avons donc besoin de trouver une autre méthode. Nous pouvons voir une comparaison de mots de passe, en effet le script tente de vérifier si le mot de passe saisi par l’utilisateur est le bon en le comparant avec le $DB_PASS.
Or, le script n’utilise pas de guillemets pour entourer les variables qu’il compare, cette petite différence peut entraîner de graves risques de sécurité. Par exemple nous pourrions utiliser des charactères spéciaux qui ont un comportement spécifique en bash comme le Pattern Matching.
Essayons donc ceci : nous allons entrer “*” comme mot de passe et ça marche, le script l’accepte. Nous pouvons donc exécuter le script même si nous ne connaissons toujours pas le mot de passe. Cela signifie que nous pouvons deviner le mot de passe en essayant chaque caractère un par un et en ajoutant un astérisque à la fin.
Nous pouvons maintenant écrire un petit programme qui devrait fonctionner tant que le mot de passe ne contient pas certains caractères spéciaux tels que “?” ou qui contourneraient également la comparaison de chaînes lorsqu’ils sont combinés avec “*”.
Devenir root
Il est temps d’écrire rapidement un code Python. Nous voulons appeler le script, essayer un caractère, y ajouter “*” et vérifier si la sortie standard du script renvoie « Mot de passe confirmé ! ». Si c’est le cas, nous conservons le caractère nouvellement trouvé et en ajoutons un nouveau jusqu’à obtenir le mot de passe complet :
La dernière chose que nous allons faire est d’exécuter le script Python sur notre cible. Nous espérons que le mot de passe root ne contient aucun caractère ?, ou *, mais nous avons de la chance et cela fonctionne, nous avons obtenu un mot de passe ! La dernière chose à faire est de nous élever au rang d’utilisateur root et de récupérer les drapeaux.








