L'iniezione sql è una tecnica (della famiglia del code injection) che tenta di manipolare query su un database per ottenere informazioni o comunque per interagire con il db più di quanto l'applicazione non permetta nativamente.
Sappiamo che un'applicazione web può essere strutturata in modo da recuperare dati da un database. Per fare questo, nelle fasi di navigazione dell'utente, l'applicazione effettua delle query verso la base dati per recuperare informazioni o altro. Spesso queste query vengono generate in seguito a un'operazione "attiva" dell'utente come per esempio l'inserimento di una parola chiave per una ricerca o l'inserimento di username e password per accedere a un'area protetta.
Le condizioni ideali per testare le vulnerabilità di sql injection sono la conoscenza della base dati e l'accesso al sorgente dell'applicazione, visto che quasi mai questo è possibile, ci accontentiamo di scoprire su quale db lavora l'applicazione e per quanto possibile proviamo a risalire alla logica analizzando i comportamenti dell'applicazione.
Abbiamo due possibili strade da seguire: utilizzare un software che effettui la scansione in automatico oppure studiare i pattern conosciuti per manipolarli e trovarne altri.
Visto che questa guida vi vuole dare le basi per comprendere la sicurezza di una applicazione web, vediamo alcuni patterns, lasciando alla curiosità del lettore la ricerca di strumenti automatici o semi-automatici.
Nota: i patterns che seguono sono di dominio pubblico da anni! Sono ottimi per evidenziare i problemi di sicurezza ma è molto improbabile che qualche applicazione sia ancora vulnerabile.
Bypassare un meccanismo di login.
Immaginiamo una procedura che richieda l'inserimento di username e password per venire autenticati dal sistema. Riusciamo a capire (grazie a un'analisi empirica e alla nostra esperienza) che la query inviata al server è del tipo
Select * from utenti where username = 'utente' and password= 'pwd'
Dove utente è il nome utente che abbiamo scritto e pwd è la password Se la query restituisce un record, lo comunica all'applicazione che ci riconosce e ci autentica. Supponiamo che esista un utente "admin" cosa farà mai questo utente? L'amministratore? Forse.
Se vogliamo tentare di essere autenticati come "admin" senza conoscere la password, possiamo ragionare così. Quello che io scrivo nel campo di testo username viene inserito nella query come valore di username. Posso manipolare la query in modo che non vada a cercare (e verificare) la password corrispondente allo user inserito?
Si, se nella casella di testo username scrivo questo: admin'-- ottengo la seguante query
Select * from utenti where username = 'admin'-- ' and password= 'pwd'
Sapendo che i due trattini (--) nel linguaggio Sql commentano quello che segue, la nostra query restituirà il record dell'utente admin (senza verificare la password)
Se volessi recuperare tutta la lista degli utenti? Nella casella username scriverò questo: 'OR 1=1-- che mi genererà una query così:
Select * from utenti where username = ''OR 1=1 -- ' and password= 'pwd'
Che significa : restituisci tutti gli utenti che hanno user='' oppure 1=1
Metodi avanzati
Questa breve introduzione (per la verità trita e ritrita in siti, forum, libri) ci serve per introdurre dei metodi di valutazione più evoluti..con un esempio.
Non essendo il linguaggio SQL uguale per tutti (i database), dobbiamo innanzitutto determinare quale database stiamo tentando di attaccare. Tra i vari metodi (non sempre attendibili) vi è quello di determinare come viene interpretata la concatenazione di stringhe. Immaginiamo di poter determinare il risultato della nostra query . In un modulo di ricerca digitiamo una parola, l'applicazione invia la query al database che risponde con la parola digitata e gli eventuali risultati.
La query potrebbe essere:
select * from ricerca where chiavediricerca= 'paroladigitata'
Al di la del risultato, la nostra word di ricerca è paroladigitata. Possiamo provare a individuare quale db sta dietro la nostra applicazione sapendo che:
- oracle concatena le stringhe così: 'parola'||'digitata'
- sqlserver concatena le stringhe così: 'parola'+'digitata'
- mysql concatena le stringhe così: 'parola' 'digitata'
Testiamo:
select * from ricerca where chiavediricerca= 'parola'||'digitata' select * from ricerca where chiavediricerca= 'parola'+'digitata' select * from ricerca where chiavediricerca= 'parola' 'digitata'
Se il database è uno di quelli di cui abbiamo tentato la concatenazione utilizzando la sua specifica sintassi, avremo come risposta dall'applicativo :
la parola cercata è paroladigitata
La tecnica di sql injection può rivelarsi estremamente efficace nell'attacco di una applicazione web , la condizione di tale efficacia è però la piena consapevolezza di ciò che si sta facendo. Posso consigliare di imparare bene le strutture (del linguaggio) sql dei diversi database per poter agire in sicurezza e con buoni risultati. È decisamente inutile riportare lunghi elenchi di query e script già pronti e lanciarle a caso.
Sarà la vostra esperienza e conoscenza a farvi capire come e quando procedere con attacchi automatici a un database.