SQL Injection spiegato: come gli attaccanti rubano dati dai siti aziendali
Che cos'e la SQL Injection
La SQL injection e la piu vecchia e ancora una delle piu dannose vulnerabilita delle applicazioni web. Esiste dalla fine degli anni '90 e, nonostante decenni di consapevolezza, continua a comparire nei siti in produzione con una frequenza allarmante. I dati OWASP, raccolti analizzando migliaia di applicazioni, hanno trovato falle di injection nel 94% delle app testate. Questo numero dovrebbe preoccupare ogni imprenditore.
Il concetto e semplice: quando un sito web prende l'input dell'utente (un modulo di login, una casella di ricerca, un parametro URL) e lo inserisce direttamente in una query al database senza una corretta sanitizzazione, un attaccante puo iniettare i propri comandi SQL. Invece di inserire un nome utente, inserisce un frammento di codice per il database. Il server esegue quel codice come se fosse una query legittima, e l'attaccante ottiene accesso a dati che non dovrebbe mai vedere.
Se il vostro sito aziendale conserva dati dei clienti, ordini, indirizzi email o qualsiasi altra informazione in un database, la SQL injection e una minaccia che dovete comprendere. Non a livello teorico, ma in termini pratici: come fa concretamente un attaccante, e come lo fermate?
Come funziona una query al database normale
Prima di guardare l'attacco, capiamo cosa succede quando le cose funzionano correttamente. Immaginate un modulo di login sul vostro sito. Un utente inserisce il suo nome utente e la password e clicca "Accedi." Dietro le quinte, il vostro sito costruisce una query al database che assomiglia a questa:
SELECT * FROM users WHERE username = 'marco' AND password = 'miapassword123'
Il database riceve questa query, cerca una riga dove il nome utente e "marco" e la password corrisponde, e restituisce il risultato. Se trova una corrispondenza, l'utente accede. Se no, vede un messaggio di errore. Semplice e logico.
Il problema inizia quando l'applicazione costruisce questa query concatenando stringhe, incollando direttamente l'input dell'utente nella stringa SQL. Il codice dietro il modulo potrebbe essere cosi:
query = "SELECT * FROM users WHERE username = '" + inputUtente + "' AND password = '" + inputPassword + "'"
Quella variabile inputUtente contiene qualsiasi cosa l'utente abbia digitato. Se digita un nome utente normale, tutto funziona. Ma cosa succede se digita qualcos'altro?
SQL Injection classica: l'attacco base
Invece di digitare un nome utente, un attaccante scrive questo nel campo username:
' OR '1'='1' --
L'applicazione incolla questo nella query, producendo:
SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = 'qualsiasi'
Scomponiamo cosa e successo. L'apostrofo dopo la stringa vuota chiude il valore del nome utente. Il OR '1'='1' aggiunge una condizione sempre vera. Il -- e un marcatore di commento SQL, che dice al database di ignorare tutto cio che segue, compreso il controllo della password. Il risultato: il database restituisce tutti gli utenti, perche '1'='1' e sempre vero. L'attaccante ha effettuato l'accesso, di solito come il primo utente nella tabella, che spesso e l'amministratore.
Questa e la forma piu semplice di SQL injection, e ha causato violazioni in aziende di ogni dimensione. La violazione di Heartland Payment Systems nel 2008, che ha esposto 130 milioni di numeri di carte di credito, e iniziata con un attacco SQL injection.
Estrazione dati con attacchi UNION
Il bypass del login e solo l'inizio. L'uso piu pericoloso della SQL injection e l'estrazione di dati. Un attaccante usa l'operatore SQL UNION per aggiungere query addizionali a quella originale e ottenere dati da qualsiasi tabella del database.
Per esempio, se un sito ha una ricerca prodotti che interroga il database cosi:
SELECT nome, prezzo FROM prodotti WHERE categoria = 'elettronica'
Un attaccante puo modificare l'input in:
elettronica' UNION SELECT username, password FROM users --
La query risultante diventa:
SELECT nome, prezzo FROM prodotti WHERE categoria = 'elettronica' UNION SELECT username, password FROM users --'
Ora la pagina che doveva mostrare i prodotti visualizza anche ogni nome utente e password memorizzati nella tabella utenti. L'attaccante vede questi dati direttamente nella pagina, formattati come se fossero informazioni sui prodotti.
Blind SQL Injection: quando non si vede l'output
Non tutte le vulnerabilita SQL injection producono un output visibile. A volte l'applicazione non mostra i risultati della query nella pagina. In questi casi, gli attaccanti usano la blind SQL injection, piu lenta ma altrettanto efficace.
Blind SQLi basata su booleani
L'attaccante invia query che pongono al database domande vero-o-falso. In base a come la pagina si comporta diversamente (mostra contenuto o mostra un errore, si carica o no), l'attaccante deduce un bit di informazione alla volta.
Per esempio, per estrarre il primo carattere della password dell'admin:
' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin') = 'a' --
Se la pagina si carica normalmente, il primo carattere e 'a'. Se mostra un errore o un comportamento diverso, l'attaccante prova 'b', poi 'c', e cosi via. Carattere per carattere, ricostruisce l'intera password. Strumenti automatizzati come sqlmap possono farlo in pochi minuti.
Blind SQLi basata sul tempo
Quando nemmeno il comportamento della pagina cambia, gli attaccanti usano il timing. Iniettano query che fanno pausare il database per una durata specifica se una condizione e vera:
' AND IF((SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a', SLEEP(5), 0) --
Se la pagina impiega 5 secondi a rispondere, il primo carattere e 'a'. Se risponde immediatamente, non lo e. Questa tecnica e piu lenta ma funziona contro applicazioni che mostrano risposte identiche indipendentemente dal risultato della query.
SQL Injection di secondo ordine
Questa e la variante che coglie di sorpresa anche gli sviluppatori esperti. Nella SQL injection di secondo ordine, l'input malevolo viene memorizzato in modo sicuro nel database durante la prima interazione (ad esempio, durante la registrazione). Viene correttamente sottoposto a escape quando memorizzato. Ma quando quel valore memorizzato viene successivamente recuperato e usato in una query diversa senza essere nuovamente sanitizzato, l'iniezione si esegue.
Esempio: un utente si registra con il nome utente admin'--. La query di registrazione usa prepared statements, quindi il valore viene memorizzato in sicurezza. Successivamente, l'applicazione ha una funzione di cambio password che costruisce una query cosi:
UPDATE users SET password = 'nuovapass' WHERE username = '" + usernameMemorizzato + "'
Quando il nome utente memorizzato admin'-- viene inserito in questa query, diventa:
UPDATE users SET password = 'nuovapass' WHERE username = 'admin'--'
L'attaccante ha appena cambiato la password dell'admin. L'input ha superato la validazione iniziale perfettamente, ma il secondo utilizzo di quei dati ha creato la vulnerabilita.
Cosa fanno gli attaccanti dopo essere entrati
Capire gli obiettivi dell'attaccante aiuta a comprendere perche la SQL injection e presa cosi seriamente:
- Esfiltrazione dati: Nomi dei clienti, indirizzi email, numeri di telefono, cronologia acquisti, dati di pagamento. Questo e l'obiettivo principale per la maggior parte degli attaccanti. I dati vengono venduti sui mercati del dark web o usati per phishing mirato.
- Bypass dell'autenticazione: Accedere come amministratore per ottenere il controllo completo dell'applicazione, modificare contenuti, installare backdoor o reindirizzare il traffico.
- Modifica dei dati: Cambiare prezzi, alterare registrazioni di ordini, inserire contenuti malevoli nelle pagine servite ad altri utenti.
- Escalation dei privilegi: Usare l'accesso al database per leggere file di configurazione del server, eseguire comandi del sistema operativo (su sistemi mal configurati) o spostarsi verso altri sistemi nella rete.
- Denial of service: Eliminare tabelle, cancellare record o eseguire query ad alto consumo di risorse che mettono in ginocchio il server del database.
Per una PMI svizzera, le conseguenze includono non solo il danno diretto ma anche violazioni della Legge federale sulla protezione dei dati (nLPD) se i dati dei clienti vengono esposti attraverso una vulnerabilita prevenibile. Abbiamo trattato il costo completo di una violazione nel nostro articolo sul costo di un sito web hackerato per le PMI.
Perche la SQL Injection e ancora cosi comune
Ci si potrebbe chiedere come una vulnerabilita scoperta negli anni '90 colpisca ancora la maggioranza delle applicazioni web. Diversi fattori contribuiscono:
- Codice legacy: Siti web costruiti anni fa con pratiche di sviluppo obsolete sono ancora in produzione. Nessuno ha riscritto il livello database. Lo sviluppatore originale potrebbe non essere piu coinvolto.
- Sviluppatori inesperti: Non tutti gli sviluppatori hanno una formazione sulla sicurezza. Molti imparano a costruire funzionalita prima e pensano alla sicurezza dopo, se ci pensano. La concatenazione di stringhe e il primo approccio insegnato da molti tutorial.
- Costruzione dinamica delle query: Alcune applicazioni richiedono query complesse che cambiano struttura in base alle selezioni dell'utente (filtri, ordinamento, operatori di ricerca). Gli sviluppatori a volte ricorrono alla concatenazione di stringhe quando trovano i prepared statements scomodi per questi scenari.
- Falsa sicurezza dagli ORM: I framework Object-Relational Mapping gestiscono automaticamente la generazione SQL, ma gli sviluppatori possono comunque scrivere query raw quando l'ORM non supporta cio che serve. Quelle query raw spesso mancano di parametrizzazione adeguata.
- Nessuna revisione del codice o test: Molti siti web di PMI vengono costruiti da un singolo sviluppatore o una piccola agenzia senza revisione del codice, test di sicurezza o budget per penetration testing.
Violazioni reali causate da SQL Injection
Non sono scenari teorici. La SQL injection e stata dietro alcune delle piu grandi violazioni di dati della storia:
| Incidente | Anno | Impatto |
|---|---|---|
| Heartland Payment Systems | 2008 | 130 milioni di numeri di carte di credito rubati |
| Sony Pictures | 2011 | 77 milioni di account PlayStation Network compromessi |
| Yahoo | 2012 | 450.000 credenziali trapelate tramite SQL injection su Yahoo Voices |
| TalkTalk | 2015 | 157.000 record clienti rubati, multa da 400.000 sterline |
| Equifax | 2017 | 147 milioni di record esposti |
E queste sono le violazioni che finiscono sui giornali. Migliaia di aziende piu piccole vengono compromesse tramite SQL injection ogni anno senza alcuna divulgazione pubblica. Una piccola azienda a Lugano o nel Ticino con un modulo di contatto o un catalogo prodotti vulnerabile e esposta tanto quanto una grande azienda, spesso di piu perche non ha il monitoraggio di sicurezza per rilevare l'attacco.
Prevenzione: Prepared Statements (Query parametrizzate)
La difesa piu efficace contro la SQL injection sono i prepared statements, chiamati anche query parametrizzate. Invece di costruire una stringa SQL incollando l'input dell'utente, si definisce la struttura della query con segnaposto e si passa l'input dell'utente separatamente:
Vulnerabile (concatenazione di stringhe):
query = "SELECT * FROM users WHERE username = '" + inputUtente + "'"
Sicuro (prepared statement):
query = "SELECT * FROM users WHERE username = ?" con parametro [inputUtente]
Con un prepared statement, il database sa che il segnaposto e un valore di dato, non parte della struttura SQL. Anche se l'utente digita ' OR '1'='1' --, il database tratta l'intera stringa come un valore letterale di nome utente. Cerca un utente chiamato ' OR '1'='1' --, non ne trova nessuno e restituisce nessun risultato. L'iniezione fallisce completamente.
Ogni linguaggio di programmazione moderno e driver di database supporta i prepared statements:
- PHP: PDO con
prepare()eexecute(), o MySQLi conprepare() - Python: Database API con
cursor.execute(query, params) - Java: Classe
PreparedStatementin JDBC - Node.js: La maggior parte delle librerie database supporta query parametrizzate di default
- C# / .NET:
SqlCommandconSqlParameter
Non ci sono scuse per non usarli. Se il vostro sviluppatore o agenzia web costruisce query con concatenazione di stringhe, e un segnale di allarme serio sulle loro pratiche di sicurezza.
Prevenzione: Validazione dell'input
I prepared statements sono la difesa primaria, ma la validazione dell'input aggiunge un secondo livello. Il principio e semplice: definite come deve apparire un input valido e rifiutate tutto il resto.
- Whitelist invece di blacklist: Non provate a filtrare i caratteri pericolosi. Piuttosto, definite cosa e permesso. Se un campo deve contenere un numero, validate che contenga solo cifre. Se deve essere un'email, validate il formato.
- Controllo del tipo: Se un parametro URL deve essere un intero (come un ID prodotto), convertitelo in intero prima di usarlo.
parseInt("1 OR 1=1")restituisce1oNaN, nessuno dei quali e iniettabile. - Limiti di lunghezza: I payload di SQL injection tendono ad essere piu lunghi dell'input legittimo. Un campo nome utente limitato a 30 caratteri da meno spazio a un attaccante per creare un payload funzionante.
- Codifica dell'output: Anche se l'iniezione fallisce a livello SQL, la codifica dell'output impedisce che contenuto malevolo memorizzato venga renderizzato come codice nel browser (questo si sovrappone alla prevenzione XSS, che trattiamo nel nostro articolo XSS spiegato).
Prevenzione: Web Application Firewall (WAF)
Un WAF si posiziona tra gli utenti e la vostra applicazione web, ispezionando ogni richiesta alla ricerca di pattern che sembrano attacchi. I WAF moderni possono rilevare e bloccare tentativi di SQL injection in tempo reale.
Un WAF e un livello di difesa prezioso, ma non sostituisce la scrittura di codice sicuro. I WAF possono essere aggirati. Gli attaccanti sviluppano costantemente nuove tecniche di encoding e variazioni di payload per eludere le regole del WAF. Pensate a un WAF come a una rete di sicurezza, non un sostituto per costruire la casa correttamente.
Opzioni per WAF:
- WAF cloud-based: Cloudflare, Sucuri, AWS WAF. I piu facili da implementare e funzionano bene per la maggior parte dei siti PMI.
- WAF a livello server: ModSecurity con OWASP Core Rule Set. Piu configurabile ma richiede competenze di amministrazione server.
- WAF a livello applicazione: Librerie e middleware che ispezionano le richieste all'interno del codice applicativo.
Prevenzione: Accesso al database con privilegio minimo
Anche se un attaccante riesce a iniettare SQL, potete limitare il danno restringendo cio che l'utente del database puo fare. L'account database dell'applicazione dovrebbe avere i permessi minimi necessari per funzionare:
- Se l'applicazione legge solo dati da una tabella, l'utente database non dovrebbe avere permessi di scrittura su quella tabella.
- L'utente database dell'applicazione non dovrebbe mai avere permessi
DROP TABLEoDROP DATABASE. - Le operazioni amministrative sul database (modifiche allo schema, gestione utenti) dovrebbero usare un account separato e piu privilegiato che l'applicazione non tocca mai.
- Considerate di usare utenti database diversi per parti diverse dell'applicazione (es. uno per il sito pubblico, un altro per il pannello admin).
Prevenzione: Test di sicurezza
Non potete correggere quello che non trovate. I test di sicurezza regolari sono il modo per scoprire vulnerabilita SQL injection prima degli attaccanti.
- Scansione automatizzata: Strumenti come OWASP ZAP (gratuito), Burp Suite o Acunetix possono scansionare il vostro sito alla ricerca di SQL injection e altre vulnerabilita. Eseguite queste scansioni dopo ogni modifica significativa al codice.
- Penetration testing manuale: Gli strumenti automatizzati trovano i casi ovvi. Un penetration tester esperto trovera iniezioni di secondo ordine, falle logiche e vulnerabilita specifiche del contesto che gli scanner non vedono.
- Revisione del codice: Fate rivedere il codice del livello database da qualcuno diverso dallo sviluppatore originale, cercando specificamente costruzione di SQL raw senza parametrizzazione.
Offriamo servizi di valutazione della sicurezza per le aziende a Lugano e in tutta la Svizzera. Se non siete sicuri se il vostro sito e vulnerabile, contattate il nostro team per una valutazione approfondita.
Cosa fare se sospettate che il vostro sito sia vulnerabile
- Non fatevi prendere dal panico, ma agite in fretta. La SQL injection e seria ma risolvibile.
- Chiedete direttamente al vostro sviluppatore o agenzia: "Stiamo usando prepared statements per tutte le query al database?" Se esitano o non sono sicuri, avete la vostra risposta.
- Eseguite una scansione automatizzata. OWASP ZAP e gratuito e puo identificare i pattern di SQL injection piu comuni.
- Implementate un WAF immediatamente. Il piano gratuito di Cloudflare include protezione WAF di base e puo essere configurato in meno di un'ora. Questo vi fa guadagnare tempo mentre correggete il codice sottostante.
- Controllate i log. Cercate richieste contenenti parole chiave SQL come
UNION,SELECT,DROPo caratteri inusuali come apostrofi e punti e virgola nelle sottomissioni dei form. - Date priorita alla correzione. Non aspettate il prossimo ciclo di sviluppo. La SQL injection e una vulnerabilita da correggere subito.
Per una visione piu ampia delle vulnerabilita delle applicazioni web, consultate la nostra analisi della OWASP Top 10, dove l'injection occupa una posizione di rilievo.
La conclusione per gli imprenditori
La SQL injection non e esotica o sofisticata. E una vulnerabilita ben compresa con difese ben comprese. Il fatto che appaia ancora nella maggioranza delle applicazioni web e un fallimento delle pratiche di sviluppo, non un fallimento delle soluzioni disponibili.
Se il vostro sito ha un database dietro (e se ha un modulo di login, una funzione di ricerca, un catalogo prodotti o un modulo di contatto che memorizza le richieste, quasi certamente ce l'ha), ponete la domanda: come vengono costruite le nostre query al database? La risposta dovrebbe sempre essere "con prepared statements." Qualsiasi altra cosa e un rischio che la vostra azienda non dovrebbe portare.
Vuoi sapere se il tuo sito è sicuro?
Richiedi un audit di sicurezza gratuito. In 48 ore ricevi un report completo.
Richiedi Audit Gratuito