Guida alle tecnologie

Proteggere il database dagli attacchi SQL Injection

• 7 min read • Sicurezza • Aggiornato 27 Sep 2025
Protezione da SQL Injection nei database
Protezione da SQL Injection nei database

Rappresentazione grafica del rischio di SQL injection su un database

Perché questo articolo è utile

Questo articolo spiega in modo pratico come avvengono le SQL injection e mostra misure concrete per prevenirle. È pensato per sviluppatori, amministratori di database e team di sicurezza che vogliono ridurre il rischio e prepararsi a rispondere a un incidente.

Cos’è una SQL injection (breve definizione)

Una SQL injection è un attacco in cui un aggressore inserisce codice SQL malevolo in un campo di input, inducendo il database a eseguire comandi non previsti. In una frase: dati malevoli trasformati in codice.

Come avviene un attacco SQL injection

Un’applicazione compone una query SQL includendo direttamente i dati forniti dall’utente. Se quei dati non vengono filtrati o separati dalla struttura della query, un’aggiunta malevola può cambiare la logica della query.

Esempio concettuale: un campo password che contiene: ‘ OR ‘1’=’1 Se la stringa viene concatenata senza protezioni, la condizione diventa sempre vera e l’attaccante ottiene accesso.

Esempio vulnerabile in PHP

Di seguito un semplice esempio che illustra il problema. Non eseguire codice non sicuro in produzione.

Se l’utente passa username=computer e password=comp123, la query normale cercherà il record corrispondente. Ma se l’attaccante invia password = ‘ OR ‘a’=’a, la query si trasforma e la condizione può risultare sempre vera, consentendo l’accesso senza credenziali valide.

Tipi comuni di SQL injection (panoramica)

  • Error-based: l’attaccante sfrutta messaggi di errore dettagliati.
  • Union-based: l’attaccante unisce risultati arbitrari.
  • Boolean-based blind: inferenze tramite risposte true/false.
  • Time-based blind: inferenze tramite ritardi nelle risposte.

Important: non tutti gli attacchi restituiscono dati visibili; alcuni sono “blind” e richiedono tecniche diverse.

Strategie principali per proteggere il database

Di seguito le tecniche più efficaci, con esempi pratici e raccomandazioni.

1. Usare query parametrizzate (prepared statements)

Le query parametrizzate separano i dati dalla struttura SQL. I placeholder non possono modificare la sintassi della query.

Esempio con PDO (PHP) — consigliato:

 PDO::ERRMODE_EXCEPTION,
]);
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username AND user_password = :password');
$stmt->execute([':username' => $_POST['username'], ':password' => $_POST['password']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
?>

Esempio con MySQLi (prepared statements):

prepare('SELECT * FROM users WHERE username = ? AND user_password = ?');
$stmt->bind_param('ss', $_POST['username'], $_POST['password']);
$stmt->execute();
$result = $stmt->get_result();
?>

Quando possibile, preferisci i prepared statements a ogni forma di escaping manuale.

2. Sanitizzare e validare gli input (lato server)

Sanitizzazione: rimuovere o neutralizzare caratteri potenzialmente pericolosi. Validazione: confermare che il dato rispetti formato, lunghezza e tipo attesi.

Regole pratiche:

  • Applica whitelist dei caratteri per identificatori, numeri, email.
  • Rimuovi spazi superflui, newline e caratteri di controllo.
  • Limita la lunghezza massima dei campi.
  • Fallisci sicuro: rifiuta input che non rispettano le regole.

Esempio di sanitizzazione con mysqli_real_escape_string (se non si usano prepared statements):

Nota: l’escaping è una misura utile ma meno sicura e più soggetta a errori rispetto alle query parametrizzate.

3. Principio del privilegio minimo (restrict database permissions)

Non usare account con privilegi elevati per le connessioni applicative. Concedi solo ciò che serve (SELECT/INSERT/UPDATE/DELETE specifici).

Esempio su Microsoft SQL Server:

deny select on sys.tables to sqldatabasepermit;
deny select on sys.packages to sqldatabasepermit;
deny select on sys.sysobjects to sqldatabasepermit;

Altre raccomandazioni:

  • Separare account di lettura e scrittura se possibile.
  • Non usare account dbo/sysadmin dalle applicazioni.
  • Audita i permessi e rimuovi accessi inutilizzati.

4. Non divulgare messaggi di errore dettagliati

Mostra all’utente messaggi generici. Logga i dettagli a parte in un sistema protetto (SIEM). I messaggi di errore possono aiutare un attaccante a costruire payload efficaci.

5. Web Application Firewall (WAF) e regole layered

Il WAF può bloccare payload noti e pattern sospetti. Consideralo come parte di una difesa a più livelli, non come unica protezione.

6. Monitoraggio, logging e alerting

  • Logga query fallite e tentativi di input sospetti.
  • Definisci alert per pattern ripetuti (es. molte richieste con caratteri speciali).
  • Conserva i log in modo immutabile per analisi post-incidente.

7. Test e verifica continua

Integra scanner di vulnerabilità, test di penetrazione e test automatizzati nel CI/CD.

Esempi di test:

  • Test che inviano payload di SQL injection noti e verificano che la risposta sia gestita.
  • Test di regressione per sanitizzazione e validazione.

Quando le contromisure falliscono (controesempi e limiti)

  • Codice legacy che usa concatenazione di stringhe senza refactor.
  • Stored procedure che generano SQL dinamico senza sanificazione.
  • Privilegi eccessivi: anche query parametrizzate non evitano perdita di dati se l’account ha permessi elevati.
  • Configurazioni errate del database o errori di deploy che attivano debug e messaggi di errore in produzione.

Importante: la difesa migliore combina più misure.

Mini-metodologia: approccio in quattro fasi

  1. Scoprire: esegui scansioni e mapping degli input esposti.
  2. Proteggere: applica query parametrizzate e validazione.
  3. Limitare: riduci i privilegi e segmenta accessi.
  4. Verificare: test automatici e pen-test periodici.

Playbook operativo (passi rapidi per sviluppatori e DBA)

  • Sviluppatore: sostituisci concatenazioni con prepared statements; aggiungi validazione lato server; scrivi test che attestino il comportamento.
  • DBA: verifica gli account applicativi e riduci i permessi; abilita logging e auditing.
  • Team di sicurezza: configurare WAF, eseguire scansioni regolari e pen-test.

Incident runbook: cosa fare in caso di sospetta SQL injection

  1. Isolare l’applicazione vulnerabile (se possibile, rimuovere l’accesso pubblico temporaneamente).
  2. Abilitare raccolta log dettagliati e snapshot del database (solo in lettura).
  3. Identificare query eseguite e punti di ingresso.
  4. Ripristinare da backup coerenti se i dati sono compromessi.
  5. Rifattorizzare il codice colpevole e deployare patch.
  6. Comunicare l’incidente secondo le policy aziendali e, se necessario, agli enti regolatori.

Criteri di accettazione per una funzione di login sicura

  • Tutte le query verso l’auth layer usano prepared statements.
  • Input utente validati e limitati per lunghezza e formato.
  • L’account DB usato da login ha permessi minimi.
  • Test automatici rilevano injection note e falliscono se ci sono regressioni.

Checklist per ruolo

  • Sviluppatore:
    • Usare prepared statements sempre.
    • Validare dati lato server.
    • Scrivere test unitari e di integrazione.
  • DBA:
    • Controllare e rimuovere permessi superflui.
    • Abilitare auditing delle query sensibili.
  • Sicurezza:
    • Eseguire scan e pen-test periodici.
    • Monitorare log e configurare alert.

Privacy e conformità (GDPR e dati personali)

Se il database contiene dati personali, una violazione può avere impatti legali. Azioni raccomandate:

  • Limitare l’accesso ai dati personali solo a chi ne ha bisogno.
  • Tenere log di accesso e modificarli per la durata richiesta.
  • Preparare comunicazioni per gli interessati in caso di esposizione di dati sensibili.

Nota: consultare il team legale per obblighi di notifica specifici.

Test cases / acceptance criteria (campione)

  • Input: username contiene “‘ OR ‘1’=’1”; risultato atteso: accesso negato e log dell’evento.
  • Input: email con caratteri non validi; risultato atteso: input rifiutato con errore di validazione.
  • Load test: il WAF non introduce latenza significativa sotto carico normale.

Breve glossario (una riga ciascuno)

  • Prepared statement: query SQL con segnaposto che separa dati e codice.
  • Sanitizzazione: rimozione o modifica di caratteri per ridurre rischi.
  • Whitelist: elenco consentito di caratteri o pattern.
  • WAF: Web Application Firewall, filtro tra client e applicazione.

Valutazione impatto × sforzo (orientativa)

  • Prepared statements: impatto alto, sforzo medio (modifica del codice sorgente).
  • Validazione lato server: impatto medio, sforzo basso-medio.
  • Riduzione permessi DB: impatto alto, sforzo basso.
  • WAF: impatto medio, sforzo medio.

Riepilogo finale

La SQL injection rimane una delle vulnerabilità più sfruttate. La difesa efficace combina: query parametrizzate, validazione/sanitizzazione lato server, privilegi minimi, logging/monitoraggio e test continui. Applica la metodologia in quattro fasi e mantieni playbook e runbook pronti per rispondere a incidenti.

Note importanti:

  • Non affidarti a una sola misura di difesa.
  • Aggiorna regole di sicurezza e test regolarmente.
Autore
Redazione

Materiali simili

Installare e usare Podman su Debian 11
DevOps

Installare e usare Podman su Debian 11

Guida rapida a apt-pinning su Debian
Linux

Guida rapida a apt-pinning su Debian

Forzare FSR 4 con OptiScaler: guida completa
Guide.

Forzare FSR 4 con OptiScaler: guida completa

Dansguardian + Squid NTLM su Debian Etch
Rete

Dansguardian + Squid NTLM su Debian Etch

Riparare errore installazione SD su Android
Android

Riparare errore installazione SD su Android

Cartelle di rete con KNetAttach e remote:/
Linux

Cartelle di rete con KNetAttach e remote:/