Best Practices per l'Indurimento delle Configurazioni di Sicurezza del Server MySQL

Indurisci MySQL con utenti a privilegio minimo, restrizioni host, TLS, impostazioni my.cnf più sicure, patch e auditing di base.

Best Practices per l'Indurimento delle Configurazioni di Sicurezza del Server MySQL

L'indurimento di MySQL inizia con una domanda semplice: cosa guadagnerebbe un attaccante se una password di un'applicazione venisse compromessa? Se la risposta è "tutti i database da qualsiasi luogo", il tuo server necessita di utenti più restrittivi, regole di rete e configurazioni.

Utilizza queste pratiche per ridurre il raggio d'esplosione di una compromissione senza rendere l'amministrazione quotidiana dolorosa.

1. Gestione degli Utenti e degli Accessi: Il Principio del Minimo Privilegio

Una gestione efficace degli utenti è fondamentale per la sicurezza di MySQL. Concedere agli utenti solo i permessi di cui hanno assolutamente bisogno è fondamentale.

Creare Utenti Specifici per Applicazioni Specifiche

Evita di utilizzare l'utente root per le connessioni delle applicazioni. Invece, crea utenti dedicati con permessi granulari.

CREATE USER 'my_app_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON `your_database`.* TO 'my_app_user'@'localhost';

Applicare Password Forti

Password forti e uniche sono la tua prima linea di difesa. Utilizza il plugin di validazione delle password integrato di MySQL, se disponibile.

  • Complessità: Mescola maiuscole, minuscole, numeri e simboli.
  • Lunghezza: Punta ad almeno 12-16 caratteri.
  • Unicità: Non riutilizzare mai le password.
  • Rotazione: Implementa una politica per cambi regolari delle password.

Puoi abilitare il componente validate_password (MySQL 8.0+) o il plugin (MySQL 5.7+):

INSTALL COMPONENT 'file://component_validate_password';
-- OPPURE per versioni precedenti
INSTALL PLUGIN validate_password SONAME 'validate_password.so';

-- Configura la politica di forza (es. MEDIUM per 8+ caratteri, mix maiuscole/minuscole, numeri, speciali)
SET GLOBAL validate_password.policy = MEDIUM;
SET GLOBAL validate_password.length = 12;

Rimuovere Utenti Predefiniti e Inutilizzati

MySQL può includere account amministrativi e interni. Mantieni gli account di sistema necessari come mysql.session e mysql.sys, ma rimuovi gli account anonimi e qualsiasi account umano o applicativo che non usi più.

-- Per identificare utenti anonimi:
SELECT user, host FROM mysql.user WHERE user = '';
-- Per eliminare un utente anonimo (se trovato):
DROP USER ''@'localhost';

-- Per rimuovere database di test (se esistono):
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';
FLUSH PRIVILEGES;

Limitare l'Accesso Host

Limita gli account utente a connettersi solo da indirizzi IP o nomi host specifici. Evita di usare % come carattere jolly per l'host a meno che non sia assolutamente necessario e abbinato ad altri forti controlli di sicurezza.

-- L'utente può connettersi solo da localhost
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'AnotherStrongPass!';

-- L'utente può connettersi solo da un indirizzo IP specifico
CREATE USER 'backup_user'@'192.168.1.100' IDENTIFIED BY 'BackupPass!';

Essere Cauti con GRANT OPTION

La clausola WITH GRANT OPTION permette a un utente di concedere i propri privilegi ad altri utenti. Questo può rappresentare un rischio di sicurezza significativo se concesso a utenti non fidati. Usalo con parsimonia e solo per account amministrativi che ne hanno realmente bisogno.

-- Un utente con la capacità di concedere privilegi (usare con estrema cautela)
CREATE USER 'superadmin'@'localhost' IDENTIFIED BY 'SuperAdminPass!';
GRANT ALL PRIVILEGES ON *.* TO 'superadmin'@'localhost' WITH GRANT OPTION;

2. Sicurezza di Rete: Isolare il Tuo Database

I controlli a livello di rete sono fondamentali per prevenire accessi esterni non autorizzati al tuo server MySQL.

Configurare i Firewall

Consenti connessioni alla porta predefinita di MySQL (3306) solo da indirizzi IP o reti fidati. Blocca tutte le altre connessioni in entrata su questa porta.

Esempio (UFW su Linux):

sudo ufw enable
sudo ufw allow from 192.168.1.0/24 to any port 3306
sudo ufw deny 3306
sudo ufw status

Esempio (CentOS/RHEL con firewalld):

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --permanent --remove-port=3306/tcp --zone=public # Assicurati che non sia aperta globalmente
sudo firewall-cmd --reload

Proteggere le Connessioni con SSL/TLS

Cripta tutto il traffico tra i client e il server MySQL utilizzando SSL/TLS per prevenire intercettazioni e attacchi Man-in-the-Middle (MitM). Questo è particolarmente cruciale per le connessioni su reti non fidate.

Per abilitare SSL/TLS, devi generalmente generare certificati e chiavi SSL, quindi configurare il tuo my.cnf:

# my.cnf
[mysqld]
ssl_ca=/etc/mysql/certs/ca.pem
ssl_cert=/etc/mysql/certs/server-cert.pem
ssl_key=/etc/mysql/certs/server-key.pem

I client dovrebbero quindi essere configurati per connettersi utilizzando SSL/TLS, spesso con REQUIRE SSL nell'istruzione GRANT dell'utente:

CREATE USER 'ssl_user'@'%' IDENTIFIED BY 'SSLUserPass!';
GRANT SELECT ON `your_database`.* TO 'ssl_user'@'%' REQUIRE SSL;

Associare a Indirizzi IP Specifici

Per impostazione predefinita, MySQL potrebbe ascoltare su tutte le interfacce di rete disponibili (0.0.0.0). Limitarlo ad ascoltare solo sulle interfacce che devono accettare connessioni (es. localhost per applicazioni locali, o un IP di rete privata per connessioni interne).

# my.cnf
[mysqld]
bind-address = 127.0.0.1  # Solo per connessioni locali
# OPPURE
bind-address = 192.168.1.10  # Per un IP interno specifico

Suggerimento: Se la tua applicazione e il server MySQL sono sulla stessa macchina, bind-address = 127.0.0.1 (localhost) è l'opzione più sicura, poiché impedisce completamente qualsiasi connessione esterna.

3. Indurimento del File di Configurazione (my.cnf / my.ini)

Il file di configurazione di MySQL (my.cnf su Linux, my.ini su Windows) offre numerosi parametri per migliorare la sicurezza.

Disabilitare Funzionalità Inutilizzate

Minimizza la superficie di attacco disabilitando le funzionalità non necessarie per la tua implementazione.

  • local_infile = 0: Disabilita LOAD DATA LOCAL INFILE, che altrimenti può leggere file dal client host quando sia il client che il server lo consentono.
    [mysqld]
    local_infile = 0
    
  • skip-networking: Se il tuo database è accessibile solo da applicazioni sullo stesso server, disabilita completamente la rete. Questo forza tutte le connessioni a utilizzare il socket Unix o named pipes.
    [mysqld]
    skip-networking
    
  • symbolic-links = 0: Impedisce l'uso di collegamenti simbolici per i tablespace del database, che possono essere sfruttati per accedere a file al di fuori della directory dei dati di MySQL.
    [mysqld]
    symbolic-links = 0
    
  • secure_file_priv: Limita la directory utilizzata dalle operazioni di importazione ed esportazione di file come LOAD DATA INFILE e SELECT ... INTO OUTFILE.
    [mysqld]
    secure_file_priv = /var/lib/mysql-files
    

Imposta secure_file_priv su una directory dedicata di proprietà dell'account di servizio MySQL. Non puntarlo a /tmp, una directory di upload dell'applicazione o un percorso in cui utenti non fidati possono scrivere.

Evitare Segreti in Testo Chiaro nei File di Opzioni

I file di opzioni del client possono esporre accidentalmente le password del database a chiunque possa leggerli. Se devi memorizzare le credenziali per l'automazione, limita i permessi del file e utilizza un account dedicato a bassi privilegi.

chmod 600 /home/backup/.my.cnf
chown backup:backup /home/backup/.my.cnf

Per l'amministrazione interattiva, preferisci richiedere la password:

mysql -u admin -p

4. Applicare Patch e Verificare il Server

Una configurazione di sicurezza non salverà un server non aggiornato. Mantieni MySQL, le librerie client e il sistema operativo aggiornati attraverso il normale processo di aggiornamento dei pacchetti o del fornitore.

Dopo aver modificato my.cnf, convalida e riavvia durante una finestra di manutenzione:

mysqld --validate-config
sudo systemctl restart mysql
sudo systemctl status mysql

I nomi dei pacchetti e dei servizi variano a seconda della distribuzione. Alcuni sistemi usano mysqld invece di mysql.

5. Monitorare gli Accessi e Rivedere i Privilegi

L'indurimento non è finito dopo il primo passaggio. Rivedi regolarmente account e concessioni, specialmente dopo cambiamenti alle applicazioni o turnover del personale.

SELECT user, host, account_locked FROM mysql.user ORDER BY user, host;
SHOW GRANTS FOR 'my_app_user'@'localhost';

Tieni d'occhio gli account che utilizzano host %, privilegi *.* ampi, FILE, SUPER, SYSTEM_USER o WITH GRANT OPTION. Quei privilegi possono essere validi per un piccolo numero di account amministrativi, ma non dovrebbero mai apparire su utenti applicativi di routine.

Conclusione

Indurisci MySQL a strati. Inizia con utenti dedicati a privilegio minimo, limita da dove possono connettersi, crittografa il traffico quando attraversa una rete, disabilita le funzionalità rischiose che non usi e mantieni il server aggiornato. Quindi programma revisioni dei privilegi in modo che gli accessi vecchi non diventino silenziosamente il tuo prossimo incidente.