Cosa sono le SQL Injection
SQL Injection è un termine con il quale si identifica una tecnica con il quale è possibile manomettere le query SQL in applicazioni nel quale non sono stati inseriti appositi controlli.
Molto spesso negli script non viene considerata la sicurezza dell'applicazione, e questo può far si che un malitenzionato manometta il database o entri in possesso dei dati presenti nel database.

Scopo della guida
Lo scopo di questa guida è appunto quello di creare applicazioni sicure.
Per fare ciò è necessario conoscere come si fà una SQL Inection, per sapere quali parti della applicazioni sono a rischio e provvedere a rendere questi attacchi impossibili.

Configurazione di php - Magic_quotes
Alcune volte potreste trovare differenza di configurazione di php, potrebbe esserci infatti la direttiva magic_quotes su ON, questa si occupa di fare un filtraggio di base a tutti gli input.
Nella maggior parte dei casi questo filtraggio è molto utile e diminuisce moltissimo la possibilità di alterare le query, tuttavia presenta dei problemi nel caso in cui lavoriamo anche con i file.
Passando tra un hosting e l'altro potrebbe comunque esserci differenza nell'impostazione di questa direttiva, per cui quello che era "sicuro" sull'hosting X potrebbe non esserlo più se passiamo all'hosting Y.
Se fin ora molti programmatori si sono cullati su questa direttiva, da php 5.3 la direttiva è deprecata ed è stata rimossa con php 5.4, per cui d'ora in poi bisognerà fare molta attenzione alle SQL Injection. Nel caso in cui vogliamo settare la direttiva su OFF possiamo usare il seguente codice:

Codice PHP:
if(function_exists('set_magic_quotes_runtime'))
{
    @
set_magic_quotes_runtime(0);



Esempio 1 - Login


Supponiamo di avere un form di login realizato cosi:
index.html:
Codice PHP:
<form action="login.php" method="post">
Username: <input type="text" name="user" />
Password: <input type="password" name="pass" />
<
input type="submit" value="Login" />
</
form
login.php
Codice PHP:
$user $_POST['user'];
$pass $_POST['pass'];
$sql mysql_query("SELECT * FROM utenti WHERE user = '$user' AND pass = '$pass'");
if(
mysql_num_rows($sql) > 0)
{
    
// Eseguo login

Vediamo come è possibile sfruttare una SQL Injection, inseriamo come user:
Codice:
TheDarkITA
E come password:
Codice:
' OR '1' = '1
Magicamente il nostro script ci farà passare come se esiste un utente con quel nick e con quella password.
Se non ci credete, provate pure.

Esempio 2 - Login più complessi
Alcuni login controllano che venga restituito un solo record, questo non le rende immuni da SQL Injection.
In questo esempio loggheremo con l'utente admin, e l'applicazione potrebbe darci privileggi maggiori.

index.html:
Codice PHP:
<form action="login.php" method="post">
Username: <input type="text" name="user" />
Password: <input type="password" name="pass" />
<
input type="submit" value="Login" />
</
form
login.php
Codice PHP:
$user $_POST['user'];
$pass $_POST['pass'];
$sql mysql_query("SELECT * FROM utenti WHERE user = '$user' AND pass = '$pass' LIMIT 1");
if(
mysql_num_rows($sql) == 1)
{
    
// Eseguo login

Vediamo come è possibile sfruttare una SQL Injection per autenticarci come admin, inseriamo come user:
Codice:
TheDarkITA
E come password:
Codice:
' OR user = 'admin
Ed anche questa volta siamo entrati, come admin.



Altre informazioni
Effettuando una SQL Injection è possibile anche generare subquery, e manomettere query di update o delete, gli effetti potrebbero essere parecchio indesiderati anche in quei casi.
In questi 2 esempi ci siamo limitati al caso del login, che è il semplice da capire, e permette a chi legge la guida di vedere quanti problemi possa provocare la mancanza di sicurezza per le applicazioni.
In alcuni casi, con subquery, si potrebbe anche arrivare a recuperare l'intera lista di nomi utenti e password dell'applicazione. La cosa è più complicata ovviamente, e richiede delle query di partenza un pò particolari, che a me comunque è capitato di vedere utilizzate e quindi fate massima attenzione.

Come ci si difende
Bisogna effettuare il filtraggio dei dati di input sempre. Se ci aspettiamo ad esempio che un utente inserisca un dato numerico, controlliamo di aver ricevuto un numero e non una stringa di caratteri.
Nei casi dei login, per difendersi bisognerebbe filtrare gli input cosi:
Codice PHP:
$user mysql_real_escape_string($_POST['user']);
$pass mysql_real_escape_string($_POST['pass']); 
Difendersi è molto semplice, basta usare questa funzione infatti per le stringhe. Ma bisogna fare attenzione a non dimenticarlo mai, e pensare cosa può accadere se un utente manomette l'input inviando qualcosa che non ci aspettiamo normalmente di ricevere.