SQL Injection (SQLi) è un tipo di injection attack che consente di eseguire istruzioni SQL dannose. Queste istruzioni controllano un server di database dietro un’applicazione web. Gli aggressori possono utilizzare le vulnerabilità di una SQL Injection, per aggirare le misure di sicurezza delle applicazioni. Possono aggirare l’autenticazione e l’autorizzazione di una pagina web o di un’applicazione web e recuperare il contenuto dell’intero database SQL. Possono anche utilizzare SQL Injection per aggiungere, modificare ed eliminare record nel database.

Una vulnerabilità di SQL Injection può interessare qualsiasi sito Web o applicazione Web che utilizza un database SQL come MySQL, Oracle, SQL Server o altri. I criminali possono utilizzarla per ottenere l’accesso non autorizzato ai dati sensibili: informazioni sui clienti, dati personali, segreti commerciali, proprietà intellettuale e altro. Gli attacchi SQL Injection sono una delle vulnerabilità delle applicazioni Web più vecchie, prevalenti e pericolose. L’organizzazione OWASP (Open Web Application Security Project) elenca le injection nel documento OWASP Top 10 2017 come la minaccia numero uno alla sicurezza delle applicazioni web.

Come e perché viene eseguito un attacco SQL injection

Per effettuare un attacco SQL Injection, un utente malintenzionato deve prima trovare gli input degli utenti vulnerabili all’interno della pagina Web o dell’applicazione Web. Una pagina Web o un’applicazione Web che presenta una vulnerabilità SQL Injection utilizza l’input dell’utente direttamente in una query SQL. L’aggressore può creare contenuto di input. Tale contenuto è spesso chiamato payload dannoso ed è la parte fondamentale dell’attacco. Dopo che l’autore dell’attacco ha inviato questo contenuto, nel database vengono eseguiti comandi SQL dannosi.

SQL è un linguaggio di query progettato per gestire i dati archiviati nei database relazionali. Può essere usato per accedere, modificare ed eliminare i dati. Molte applicazioni Web e siti Web memorizzano tutti i dati in database SQL. In alcuni casi, è anche possibile utilizzare i comandi SQL per eseguire i comandi del sistema operativo. Pertanto, un attacco SQL Injection riuscito può avere conseguenze molto gravi.

  • Gli aggressori possono utilizzare SQL injection per trovare le credenziali di altri utenti nel database. Possono quindi impersonare questi utenti. L’utente impersonato può essere un amministratore del database con tutti i privilegi del database.
  • SQL consente di selezionare e produrre dati dal database. Una vulnerabilità SQL Injection potrebbe consentire all’autore dell’attacco di ottenere l’accesso completo a tutti i dati in un server di database.
  • SQL consente inoltre di modificare i dati in un database e aggiungere nuovi dati. Ad esempio, in un’applicazione finanziaria, un utente malintenzionato potrebbe utilizzare SQL Injection per modificare i saldi, annullare le transazioni o trasferire denaro sul proprio account.
  • È possibile utilizzare SQL per eliminare i record da un database, persino eliminare le tabelle. Anche se l’amministratore esegue backup del database, l’eliminazione dei dati potrebbe influire sulla disponibilità dell’applicazione fino al ripristino del database. Inoltre, i backup potrebbero non coprire i dati più recenti.
  • In alcuni server di database è possibile accedere al sistema operativo utilizzando il server di database. Questo può essere intenzionale o accidentale. In tal caso, un utente malintenzionato potrebbe utilizzare una SQL injection come vettore iniziale e quindi attaccare la rete interna dietro un firewall.

 

Esistono diversi tipi di attacchi SQL Injection: in-band SQLi (utilizzando errori di database o comandi UNION), blind SQLi e out-of-band SQLi. Ulteriori informazioni nei seguenti articoli: Tipi di SQL Injection (SQLi), Blind SQL Injection: che cos’è.

Per seguire passo passo come viene eseguito un attacco SQL Injection e quali gravi conseguenze può avere, vedere: Exploiting SQL Injection: a hands-on Example.

 

Semplice esempio di SQL injection

Il primo esempio è molto semplice. Mostra come un utente malintenzionato può utilizzare una vulnerabilità SQL Injection per aggirare la sicurezza dell’applicazione e autenticarsi come amministratore.

Il seguente script è uno pseudocodice eseguito su un server web. È un semplice esempio di autenticazione con un nome utente e una password. Il database di esempio ha una tabella denominata users con le seguenti colonne: username e password.

# Define POST variables

uname = request.POST[‘username’]

passwd = request.POST[‘password’]

 

# SQL query vulnerable to SQLi

sql = “SELECT id FROM users WHERE username=’” + uname + “’ AND password=’” + passwd + “’”

 

# Execute the SQL statement

database.execute(sql)

Questi campi di input sono vulnerabili ad una SQL Injection. Un utente malintenzionato potrebbe utilizzare i comandi SQL nell’input in un modo che altererebbe l’istruzione SQL eseguita dal server del database. Ad esempio, potrebbero utilizzare un trucco che coinvolge una singola virgoletta e impostare il campo passwd su:

password’ OR 1=1

Di conseguenza, il server del database esegue la seguente query SQL:

SELECT id FROM users WHERE username=’username’ AND password=‘password’ OR 1=1

A causa dell’istruzione OR 1=1, la clausola WHERE restituisce il primo id dalla tabella users indipendentemente da username e password. Il primo id utente in un database è molto spesso l’amministratore. In questo modo, l’attaccante non solo aggira l’autenticazione ma ottiene anche i privilegi di amministratore. Si può anche commentare il resto dell’istruzione SQL per controllare ulteriormente l’esecuzione della query SQL:

— MySQL, MSSQL, Oracle, PostgreSQL, SQLite

‘ OR ‘1’=’1′

‘ OR ‘1’=’1′ /*

— MySQL

‘ OR ‘1’=’1′ #

— Access (using null characters)

‘ OR ‘1’=’1′ %00

‘ OR ‘1’=’1′ %16

 

Esempio di una Union-Based SQL Injection

Uno dei tipi più comuni di SQL Injection utilizza l’operatore UNION. Consente all’attaccante di combinare i risultati di due o più istruzioni SELECT in un unico risultato. La tecnica è chiamata union-based SQL Injection.

Quello che segue è un esempio di questa tecnica. Utilizza la pagina web testphp.vulnweb.com, un sito web intenzionalmente vulnerabile ospitato da Acunetix.

La seguente richiesta HTTP è una normale richiesta inviata da un utente legittimo:

GET http://testphp.vulnweb.com/artists.php?artist=1 HTTP/1.1Host: testphp.vulnweb.com

Il parametro artist è vulnerabile ad una SQL Injection. Il seguente payload modifica la query per cercare un record inesistente. Imposta il valore nella stringa di query dell’URL a -1. Naturalmente, potrebbe essere qualsiasi altro valore che non esiste nel database. Tuttavia, un valore negativo è una buona ipotesi perché un identificatore in un database è raramente un numero negativo.

In una SQL Injection, l’operatore UNION viene comunemente utilizzato per allegare una query SQL dannosa alla query originale che deve essere eseguita dall’applicazione web. Il risultato della query inserita verrà unito al risultato della query originale. Ciò consente all’autore dell’attacco di ottenere valori di colonna da altre tabelle.

GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1, 2, 3 HTTP/1.1Host: testphp.vulnweb.com

L’esempio seguente mostra come utilizzare un payload SQL Injection per ottenere dati più significativi da questo sito intenzionalmente vulnerabile:

GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1,pass,cc FROM users WHERE uname=’test’ HTTP/1.1Host: testphp.vulnweb.com

Come prevenire un’iniezione di SQL

L’unico modo sicuro per prevenire attacchi SQL Injection è la convalida dell’input e le query parametrizzate, comprese le istruzioni preparate. Il codice dell’applicazione non dovrebbe mai utilizzare l’input direttamente. Lo sviluppatore deve disinfettare tutti gli input, non solo gli input dei moduli Web come i moduli di accesso. Devono rimuovere potenziali elementi di codice dannoso come virgolette singole. È anche una buona idea disattivare la visibilità degli errori del database sui siti di produzione. Gli errori del database possono essere utilizzati con SQL Injection per ottenere informazioni sul database.

Se si scopre una vulnerabilità da SQL Injection, ad esempio utilizzando una scansione Acunetix, potrebbe non essere possibile risolverla immediatamente. Ad esempio, la vulnerabilità potrebbe essere nel codice open source. In questi casi, è possibile utilizzare un firewall per applicazioni Web per disinfettare temporaneamente l’input.

Per informazioni su come prevenire gli attacchi SQL Injection nel linguaggio PHP, vedere: Prevenzione delle vulnerabilità di SQL Injection nelle applicazioni PHP e loro risoluzione. Per scoprire come farlo in molti altri linguaggi di programmazione diversi, fare riferimento alla guida di Bobby Tables per prevenire SQL Injection.

 

Come prevenire le SQL Injection (SQLi) – Suggerimenti generici

Prevenire le vulnerabilità da SQL Injection non è facile. Le tecniche di prevenzione specifiche dipendono dal sottotipo di vulnerabilità SQLi, dal motore di database SQL e dal linguaggio di programmazione. Tuttavia, ci sono alcuni principi strategici generali che si dovrebbero seguire per mantenere sicure le applicazioni web.

 

Step 1: Formazione e mantenimento della consapevolezza

Per mantenere sicura un’applicazione web, tutte le persone coinvolte nella creazione dell’applicazione web devono essere consapevoli dei rischi associati alle SQL Injections. Si dovrebbe fornire una formazione adeguata sulla sicurezza a tutti gli sviluppatori, al personale addetto al controllo qualità, DevOps e amministratori di sistema. Si può iniziare facendo riferimento a questa pagina.

 

Step 2: Non fidarsi dell’input dell’utente

Considerare tutti gli input dell’utente come non attendibili. Qualsiasi input dell’utente utilizzato in una query SQL introduce il rischio di una SQL Injection. L’input di utenti autenticati e/o interni, devono essere trattati allo stesso modo in cui su trattano gli input pubblici.

 

Step 3: Utilizza le whitelist, non le blacklist

Non filtrare l’input dell’utente in base alle liste nere. Un aggressore intelligente troverà quasi sempre un modo per aggirare la black list. Se possibile, verificare e filtrare l’input dell’utente utilizzando solo whitelist rigorose.

 

Step 4: Adottare le ultime tecnologie

Le vecchie tecnologie di sviluppo web non hanno protezione da SQLi. Utilizzarere l’ultima versione dell’ambiente di sviluppo, del linguaggio e le ultime tecnologie associate a tale ambiente/lingua. Ad esempio, in PHP usare PDO invece di MySQLi.

 

Step 5: Utilizzare meccanismi verificati

Non provare a creare la protezione SQLi da zero. La maggior parte delle moderne tecnologie di sviluppo può offrire meccanismi per la protezione da SQLi. Usare questi meccanismi invece di provare a reinventare la ruota. Ad esempio, utilizzare query con parametri o stored procedure.

 

Step 6: Scansionare regolarmente (con Acunetix)

Le SQL Injections possono essere introdotte dagli sviluppatori o tramite librerie/moduli/software esterni. È necessario eseguire regolarmente la scansione delle applicazioni Web utilizzando uno scanner di vulnerabilità Web come Acunetix. Se si usa Jenkins, si potrebbe installare il plugin Acunetix per scansionare automaticamente ogni build.

 

Tomasz Andrzej Nidecki (noto anche come tonid) è uno scrittore di contenuti tecnici che lavora per Acunetix. Giornalista, traduttore e scrittore tecnico con 25 anni di esperienza IT, Tomasz è stato direttore editoriale della rivista hakin9 IT Security nei suoi primi anni e gestiva un importante blog tecnico dedicato alla sicurezza della posta elettronica.