SQL Injection, ecco come difendere i tuoi dati

Datamaze
22.06.20 11:46 AM Comment(s)

Cos’è questo tipo di attacco
SQL Injection è il nome dato ad un preciso tipo di attacco informatico che prende di mira applicazioni adibite alla gestione dei dati. Nello specifico, si tratta di un’iniezione di codice, cioè un inserimento di di comandi SQL all'interno di campi di input, con lo scopo di modificare il funzionamento di un’applicazione vulnerabile.


Come funziona

Nonostante sia un attacco conosciuto e siano ormai comuni i frameworks con funzione di sanitizzazione automatica delle varie queries che interpellano un database, la SQL Injection rimane comunque al primo posto sulla classifica OWASP delle vulnerabilità più comuni. Questo perché molto spesso la realizzazione di app poco sicure è dovuta ad un errore di logica in fase di progettazione. Una falla del genere permette ad un attaccante di prendere completa visione dei dati su cui l’applicazione vittima lavora e talvolta, a seconda della configurazione, anche di eliminare o aggiungere dati.


Prendiamo come esempio un setting molto comune: un form di autenticazione con annesso database MySQL (utilizziamo qui questo tipo di sintassi SQL per semplificare l’esempio).


Pratica molto comune per  verificare l’autenticazione è quella di inviare una richiesta del genere al database:

--variabili immesse dall’esterno
@inpututente = Massimo_Beglio @inpututente2 = passwordsicura

--query eseguita a DB
SELECT *
FROM Utenti
WHERE Username = ’ ‘ + @inpututente + ‘ ’
	AND password = ’’ + @inpututente2 + ’’

Se questa semplice query trova un record con la coppia di valori corrispondente, restituisce tutte le informazioni di quel dato account e loggherà l’utente su un eventuale sito, in questo caso con le informazioni per l’username Massimo_Beglio.

In caso non venissero eseguiti alcuni controlli, un malintenzionato potrebbe costruire un semplice ma efficace vettore d’attacco per far eseguire una differente query al nostro sistema.


Mettiamo il caso che l’attaccante metta nei due campi di input i seguenti valori:

--variabili immesse dall’esterno
@inpututente =OR ‘1’ = ‘1 @inpututente2 =OR ‘1’ = ‘1

--query eseguita a DB
SELECT *
FROM Utenti
WHERE Username = ’ ‘ + @inpututente + ‘ ’
	AND password = ’’ + @inpututente2 + ’’

Una volta inseriti nella query, l’istruzione che si troverà a dover seguire il database sarà:

--variabili immesse dall’esterno
@inpututente =OR ‘1’ = ‘1 @inpututente2 =OR ‘1’ = ‘1

--query eseguita a DB
SELECT *
FROM Utenti
WHERE Username = ’‘
	OR ‘1’ = ‘1 ‘
	AND password = ’‘
	OR ‘1’ = ‘1 ‘

Questo comando non solo restituirà records (quindi login avvenuto con successo), ma restituirà anche, tra le altre, la prima row della tabella “Utenti”, che molto spesso combacia con la row dell’utente amministratore. L’eventuale programma prenderà quei dati per creare la sessione e loggare l’utente malevolo con i privilegi di amministratore. Per entrare con altri account non basterà fare altro che “giocare” con le clausole AND o LIMIT (in questo caso) inserendole nel secondo input.

Questa particolare query potrebbe benissimo anche essere usata per un attacco di tipo oracle (oracolo) ovvero creare degli statement come ad esempio:

--variabili immesse dall’esterno
@inpututente =OR ‘1’ = ‘1 @inpututente2 =OR ‘1’ = ‘1’
	AND LEFT(Username, 1) = ‘a %

--query eseguita a DB
SELECT *
FROM Utenti
WHERE Username = ’ ‘ + @inpututente + ‘ ’
	AND password = ’’ + @inpututente2 + ’’

In modo tale da capire se nel database esistono o meno username che iniziano per la lettera “a”. In caso di login con successo ve ne sono, altrimenti no. Con altri vettori ed altre tipologie di codice i danni possono essere enormi, in quanto la base dati è completamente a disposizione ed è possibile cancellare dati, modificare, aggiungere, eccetera.



Prevenzione e difesa

Sono disponibili molti metodi per la prevenzione della SQL Injection. Quello più efficace è l’utilizzo dei prepared statements, quando l’infrastruttura lo permette. Inoltre è importantissimo filtrare ogni singolo input che gli utenti possono inserire e configurare in modo efficace l’user che esegue le query a DB, per limitare eventuali danni. Un’altra tecnica da utilizzare per la sicurezza del database è quella di creare delle store procedures per le queries e dare solo i permessi di EXEC all’utente dell’applicazione che dovrà eseguirle.

C’è da ricordare che, anche utilizzando tutti i metodi visti sopra, non si è mai sicuri che il codice sia 100% SQL Injection-free, in quanto esistono tantissimi modi diversi di implementare un certo tipo di logica e altrettanti modi per contorcerla.

Rimane sempre valido il consiglio di tenere le applicazioni e i plugins costantemente aggiornati e di adottare una corretta politica per la gestione dei privilegi SQL. Inoltre è vitale rimanere aggiornati e migliorare ogni giorno l’implementazione delle proprie logiche, in modo da renderle sempre più robuste e sicure.

di Matteo Lucato, pubblicato il 20 dicembre 201