PHP  »  Guide  »  Guida sicurezza di PHP 

SQL injections



Con tale termine intendiamo tutti gli attacchi ad un'applicazione Web - nel nostro caso PHP - che consentano di modificare l'interazione della stessa con il database: nel caso vengano eseguite, lato server, interrogazioni MySQL costruite su quanto ricevuto dal client, senza un controllo sull'input è possibile che un cracker crei, "tecnicamente" parlando, disastri irrimediabili. Per una panoramica generale su queste tecniche si rimanda all'articolo Tecniche: SQL Injection pubblicato nella sezione Sicurezza di HTML.it e Proteggersi dalla SQL Injection pubblicato nella sezione PHP.

Autenticazione

Primo esempio, autenticazione utente

Riporterò ora un primo, classicissimo, esempio.

Posto che la direttiva magic_quotes_gpc del php.ini sia impostata ad OFF e non venga fatto l'escape del carattere " ' ", studiamo il caso in cui l'autenticazione degli utenti di un'ipotetica applicazione Web PHP utilizzi la seguente logica. I dati passati allo script di autenticazione giungono, come al soltio, direttamente da un form HTML.

$utente_autorizzato=0;
 
$sql="SELECT * FROM tabella_utenti
      WHERE usr='".$_POST['username']."' AND pwd='".$_POST['password']."'";
 
$query=mysql_query($sql,$db);
if (mysql_num_rows($query)>0) $utente_autorizzato=1; 

Se username e password inserite lato client sono rispettivamente marco e miapass, la query assume la forma:

SELECT * FROM tabella_utenti WHERE usr='marco' AND pwd='miapass';

A questo punto, se nel database è presente un record che soddisfi a tale query, l'utente è autorizzato ad accedere all'applicazione.

La vulnerabilità è però in agguato: se username e password inserite lato client, ossia direttamente nei moduli di autenticazione, fossero, invece, qualsiasi_nome e qualsiasi_stringa' OR 1 - -  (spazio), la query assumerebbe la diabolica forma:

SELECT * FROM tabella_utenti
WHERE usr='qualsiasi_nome' AND pwd='qualsiasi_stringa' OR 1 -- '

"- -  " rappresenta il delimitatore di commento: tutto ciò che segue viene ignorato.

Essendo la query sempre soddisfatta (ha valore di verità sempre 1), il suo risultato sarà l'intera lista degli utenti (tutte le entry della tabella) e il cracker entrerà, autenticato, nel programma.

In presenza di una qualsivoglia tipologia di riconoscimento utente, l'identità che assumerà il cracker (intendo il nome utente con cui risulterà collegato) dipende da come è strutturato il codice.

Se il primo utente di tabella_utenti è l'amministratore, molto probabilmente il cracker lo impersonificherà. Spesso infatti, presupponendo il programmatore che solo una sia la riga risultante dall'esito dell'interrogazione SQL, proprio la prima riga del record verrà associata all'utente autenticato (cracker).

Autenticazione utente con inganno sullo username

Abbiamo visto come sia possibile ottenere accesso non autorizzato inserendo stringhe (in)opportune nel campo riservato alla password. Lo stesso si può ottenere anche utilizzando il campo username.

Inserendo in username la stringa: qualsiasi_nome' OR 1 - -  (spazio)

Si ottiene:

SELECT * FROM tabella_utenti
WHERE usr='qualsiasi_nome' OR 1 -- ' AND pwd='qualsiasi_stringa';

E l'accesso è assicurato.

Autenticazione con firma sulla password

Poniamo invece subito all'attenzione una questione fondamentale: se (al contrario di come fatto finora) il sistema di autenticazione utilizza un ben più sicuro sistema di firma, per il quale la password non è memorizzata in chiaro su database ed in sua vece è memorizzato il suo hash, il programma sarà non vulnerabile al primo exploit menzionato.

Se infatti confrontiamo l'hash di quanto inserito dall'utente con ciò che è su db (già "hashato"), il comando md5 vanifica, trasparentemente, gli sforzi del cracker.

Se il codice di autenticazione fosse infatti:

$utente_autorizzato=0;
 
$sql="SELECT * FROM tabella_utenti
      WHERE usr='".$_POST['username']."' AND pwd='".md5($_POST['password'])."'";
 
$query=mysql_query($sql,$db);
if (mysql_num_rows($query) > 0)
  {
  $utente_autorizzato=1;
  }

la query, anche in presenza di tentativi di hacking (sulla password) risulterebbe simile a:

SELECT * FROM tabella_utenti
WHERE usr='qualsiasi_nome' AND pwd='6f8f57715090da2632453988d9a1501b';

e sarebbe, appunto, non vulnerabile.

Ultimi articoli PHP

Sessioni PHP: cosa sono, come si usano

Dalla configurazione di PHP, alla gestione delle sessioni in un...

Continuous Integration: automatizziamo i client con Phing

Continuous Integration: automatizziamo i client con Phing. Esempi...

Archiviazione delle applicazioni PHP con Phar

Come incorporare intere applicazioni PHP all'interno di un singolo...

I traits in PHP 5.4

Cosa sono, a cosa servono e come si unsano i traits, la novità per...

PHP 5.4: il web server integrato

Impara ad usare il web server integrato nella versione 5.4 di PHP:...

Altri articoli

Guide PHP

Guida Yii Framework

Come creare applicazioni Web in modo semplice e veloce con il...

Guida Applicazioni Facebook con PHP

Come realizzare un'applicazione per Facebook. Dalle basi della...

Guida PHP con Windows e IIS

Installare ambienti per lo sviluppo e la produzione di applicazioni...

Altre guide

Newsletter @PHP

Ogni lunedì, direttamente nella tua e-mail: script, articoli, guide e tutorial su PHP, MySQL e Apache.

Iscriviti alla newsletter

Altre newsletter

Corsi in aula

Corso PHP per Webmaster

11 Giugno 2012 a Milano
Disponibilità: 7 Posti

Corso Google AdWords Base

25 Giugno 2012 a Milano
Disponibilità: 7 Posti

Corso Google AdWords Base

05 Giugno 2012 a Roma
Disponibilità: 7 Posti