Vai al contenuto
BeoHosting
BeoHosting
Sicurezza

Come riconoscere e prevenire la SQL injection

BeoHosting Team··11 min read di lettura
Come riconoscere e prevenire la SQL injection

Che cos'è la SQL injection

La SQL injection (SQLi) è uno dei tipi di attacco più antichi e pericolosi contro le applicazioni web. L'attacco funziona iniettando codice SQL malevolo nei campi di input (form, parametri URL, cookie) che l'applicazione utilizza per costruire le query SQL verso il database. Se l'applicazione non convalida e non sanifica l'input dell'utente prima di inserirlo in una query SQL, l'attaccante può manipolare la query per leggere, modificare o cancellare dati dal database.

Secondo la lista OWASP Top 10, gli attacchi di injection figurano da anni tra le tre vulnerabilità web più critiche. Un attacco di SQL injection riuscito può comportare il furto dell'intero database (account utente, password, dati personali), la modifica o la cancellazione dei dati, il bypass dell'autenticazione (login senza password), l'esecuzione di comandi sul sistema operativo del server e la compromissione completa del server.

Come funziona la SQL injection

Principio di base

Immagina un form di login che verifica nome utente e password. L'applicazione costruisce una query SQL che assomiglia più o meno a questa: SELECT * FROM users WHERE username = 'nome_inserito' AND password = 'password_inserita'. Se l'applicazione inserisce semplicemente l'input dell'utente nella query senza alcun controllo, l'attaccante può digitare nel campo del nome utente un valore speciale che modifica la logica della query. Per esempio, un input che contiene un apostrofo seguito da codice SQL può chiudere il valore letterale della stringa e aggiungere una condizione sempre vera, bypassando il controllo della password.

Tipi di attacchi di SQL injection

Esistono diversi tipi di attacchi di SQL injection. L'In-band SQLi è il più comune, in cui l'attaccante usa lo stesso canale di comunicazione per inviare l'attacco e ricevere i risultati. Si suddivide in Error-based SQLi (sfrutta i messaggi di errore del database per estrarre informazioni) e Union-based SQLi (usa l'operatore UNION per combinare i risultati di una query malevola con una legittima). La Blind SQLi è un tipo in cui l'attaccante non vede risultati diretti ma può dedurre informazioni in base al comportamento dell'applicazione. La Boolean-based blind SQLi invia query che restituiscono vero o falso e deduce i dati carattere per carattere in base alle differenze nelle risposte. La Time-based blind SQLi usa funzioni di pausa SQL (SLEEP, WAITFOR DELAY) per determinare se una condizione è vera in base al tempo di risposta. L'Out-of-band SQLi usa un canale diverso per l'esfiltrazione dei dati, come richieste DNS o HTTP che il database invia al server dell'attaccante.

Individuare le vulnerabilità di SQL injection

Test manuali

Il modo più semplice per testare la presenza di vulnerabilità di SQL injection è iniettare caratteri speciali nei campi di input. L'apostrofo (') è il primo test: se l'applicazione restituisce un errore del database, c'è una potenziale vulnerabilità. Un doppio apostrofo ('') non dovrebbe causare errore se il singolo lo ha causato. I commenti SQL (-- o #) possono essere usati per commentare il resto della query. Gli operatori logici (OR 1=1, AND 1=2) possono rivelare vulnerabilità boolean-based. Il comando SLEEP ('; WAITFOR DELAY '0:0:5'--) rivela vulnerabilità time-based se la pagina ritarda la propria risposta.

Strumenti automatizzati

Per test sistematici, usa strumenti specializzati. SQLMap è lo strumento open source più conosciuto per il rilevamento e lo sfruttamento automatici delle vulnerabilità di SQL injection: supporta tutti i tipi di SQLi e la maggior parte dei database. Burp Suite Professional ha uno scanner integrato per la SQL injection e altre vulnerabilità web. OWASP ZAP è un'alternativa gratuita a Burp Suite con un solido scanner SQLi. Acunetix e Netsparker sono scanner commerciali di vulnerabilità web con rilevamento SQLi avanzato.

Segni di compromissione

Se sospetti che il tuo sito sia già stato bersaglio di una SQL injection, verifica quanto segue: voci insolite nei log del server web (URL con parole chiave SQL), account utente nuovi o modificati nel database (specialmente account admin), dati modificati a tua insaputa, nuovi file sul server (web shell) e un aumento del traffico verso pagine specifiche con parametri insoliti. Esamina anche i file di log del database alla ricerca di query inattese.

Prevenzione: i prepared statement

Che cosa sono i prepared statement

I prepared statement (query parametrizzate) sono la protezione più efficace contro la SQL injection. Invece di inserire l'input dell'utente direttamente in una query SQL come testo, un prepared statement separa la struttura della query dai dati. Prima viene definita la struttura della query con dei segnaposto per i dati, e poi i dati vengono inviati separatamente. Il database tratta i dati solo come valori, mai come codice SQL, rendendo impossibile l'injection.

Implementazione in diversi linguaggi

PHP con PDO (PHP Data Objects) usa il metodo prepare() per preparare una query con segnaposto (:username, :password) ed execute() con un array di valori. L'estensione MySQLi supporta i prepared statement con segnaposto ? e bind_param() per associare i valori con i relativi tipi di dato. Python con sqlite3 o psycopg2 usa segnaposto ? o %s. Java usa la classe PreparedStatement con i metodi setString() e setInt(). Le librerie Node.js come mysql2 e pg supportano le query parametrizzate con segnaposto ? o $1. Indipendentemente dal linguaggio di programmazione, il principio è lo stesso: non concatenare mai l'input dell'utente con una query SQL come stringa.

Metodi di prevenzione aggiuntivi

Validazione dell'input

Oltre ai prepared statement, convalida sempre l'input dell'utente. La validazione tramite whitelist consente solo i valori previsti: se un campo deve contenere un numero, verifica che sia davvero un numero prima di elaborarlo. Per i campi di testo, limita i caratteri consentiti, la lunghezza dell'input e il formato (regex). Non affidarti mai solo alla validazione lato client (JavaScript), perché un attaccante può aggirarla: la validazione deve essere implementata sul server.

Stored procedure

Le stored procedure sono codice SQL memorizzato ed eseguito sul server del database. Se scritte correttamente (senza SQL dinamico al loro interno), forniscono un ulteriore livello di protezione, perché l'applicazione richiama la procedura con dei parametri invece di inviare query SQL grezze. Tuttavia, le stored procedure da sole non sono una garanzia di sicurezza: se al loro interno costruiscono query dinamiche a partire dai parametri, la vulnerabilità persiste.

ORM (Object-Relational Mapping)

Le librerie ORM come Eloquent (Laravel), SQLAlchemy (Python), Hibernate (Java) e TypeORM (Node.js) usano automaticamente i prepared statement per tutte le query, eliminando gran parte del rischio di SQL injection. Tuttavia, la maggior parte degli ORM consente query SQL grezze per le operazioni complesse: in quei casi devi usare manualmente i prepared statement. Un ORM non sostituisce la conoscenza della sicurezza SQL, ma riduce notevolmente la superficie di attacco.

Principio del privilegio minimo

Configura il database in modo che l'applicazione usi un account con i privilegi minimi necessari. Un'applicazione web di norma necessita dei privilegi SELECT, INSERT, UPDATE e DELETE su tabelle specifiche. Non concedere all'account dell'applicazione i privilegi DROP, ALTER, CREATE o FILE. Se un attaccante riesce in una SQL injection, i privilegi limitati impediscono di eliminare tabelle, modificare la struttura del database e accedere al file system del server.

Protezione dalla SQL injection tramite WAF

Come un WAF rileva la SQLi

Un Web Application Firewall (WAF) analizza le richieste HTTP e blocca quelle che contengono pattern di SQL injection. Il WAF riconosce parole chiave SQL in posizioni inattese (SELECT, UNION, DROP nei parametri URL), caratteri speciali usati negli attacchi SQLi (apostrofi, commenti, operatori logici), payload SQLi noti presenti in un database di firme e anomalie nella struttura della richiesta che indicano un tentativo di injection.

Limiti del WAF

Un WAF non sostituisce il codice sicuro. Gli attaccanti esperti possono aggirare un WAF usando tecniche di encoding (URL encoding, Unicode, doppio encoding), commenti e spazi per spezzare le firme, sintassi SQL alternative che il WAF non riconosce e test incrementali per capire quali regole utilizza il WAF. Il WAF è un livello di protezione aggiuntivo (defense in depth), ma la protezione primaria deve risiedere nel codice dell'applicazione tramite prepared statement e validazione dell'input.

SQL injection in WordPress

Meccanismi di protezione di WordPress

Il core di WordPress usa il metodo $wpdb->prepare() per tutte le query al database, che è l'implementazione dei prepared statement di WordPress. Questo metodo usa segnaposto in stile sprintf (%s per le stringhe, %d per gli interi, %f per i numeri in virgola mobile) ed esegue automaticamente l'escaping dei valori. Tuttavia, le vulnerabilità compaiono più spesso in plugin e temi che non usano $wpdb->prepare() o che costruiscono le query concatenando manualmente le stringhe.

Proteggere un sito WordPress

Per proteggere un sito WordPress dalla SQL injection, aggiorna regolarmente il core di WordPress, i plugin e i temi, perché le patch di sicurezza spesso risolvono vulnerabilità SQLi. Usa solo plugin e temi provenienti da fonti affidabili (repository WordPress.org, provider commerciali noti). Installa un plugin di sicurezza (Wordfence, Sucuri, iThemes Security) che includa la protezione WAF. Consulta anche la nostra guida per proteggere un sito dagli hacker. Rimuovi plugin e temi non utilizzati, perché anche i plugin disattivati possono essere sfruttati. Limita l'accesso al database: WordPress necessita di un solo utente con accesso al proprio database.

Errori comuni che lasciano un sito vulnerabile

  • SQL dinamico nel codice: concatenare l'input dell'utente con una query SQL come stringa è la causa principale delle vulnerabilità di SQL injection. Usa sempre i prepared statement.
  • Fidarsi della validazione lato client: la validazione JavaScript può essere aggirata; ogni validazione deve esistere sul server.
  • Messaggi di errore dettagliati: mostrare agli utenti gli errori SQL rivela la struttura del database e facilita l'attacco. In produzione, registra gli errori internamente e mostra agli utenti un messaggio generico.
  • Software obsoleto: le vecchie versioni di CMS, framework e librerie hanno spesso vulnerabilità SQLi note con exploit disponibili pubblicamente.
  • Un solo utente del database per tutto: usare un account root per l'applicazione concede all'attaccante il pieno controllo del database in caso di attacco riuscito.

Conclusione

La SQL injection è una minaccia seria che può compromettere completamente il tuo sito e i dati degli utenti. La prevenzione è relativamente semplice: usa i prepared statement per tutte le interazioni con il database, convalida l'input dell'utente sul server, applica il principio del privilegio minimo e mantieni il software aggiornato. Un WAF fornisce un ulteriore livello di protezione ma non sostituisce il codice sicuro. Con l'hosting BeoHosting, tutti i server sono dotati di un WAF ModSecurity configurato che rileva e blocca i tentativi di SQL injection, ma ti consigliamo comunque di seguire nel tuo codice le migliori pratiche di programmazione sicura.

BeoHosting Team

10+ anni di esperienza — Specialisti di web hosting e infrastrutture

  • Web Hosting
  • WordPress Hosting
  • VPS
  • Dedicated Serveri
  • Domeni
  • SSL
  • cPanel
  • LiteSpeed
  • Linux administracija
  • DNS

Ultimo aggiornamento: