Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 6 di 56
  • livello intermedio
Indice lezioni

MySQLi e i prepared statement

Utilizzare i prepared statement dell'estensione MySQLi di PHP per rendere più sicure le query ed evitare gli attacchi basati sulle SQL injection.
Utilizzare i prepared statement dell'estensione MySQLi di PHP per rendere più sicure le query ed evitare gli attacchi basati sulle SQL injection.
Link copiato negli appunti

La SELECT proposta nella lezione precedente ci espone a potenziali rischi dal punto di vista dell'iniezione di codice malevolo, le sql injection infatti sono ancora al primo posto sia per la facilità di sfruttamento della vulnerabilità, sia per i rischi ad essa connessi; oltretutto, benché se ne parli da molto tempo, restano ancora diffuse.

Analizziamo il nostro codice:

$user = "pippo"; // Normalmente questi valori sarebbero ottenuti tramite POST
$password = hash('sha256', "paperino");
$query = $mysqli->query("SELECT * FROM login WHERE user = '$user' AND password = '$password'");

Il rischio è legato all'uso incauto della variabile $user che verosimilmente sarà popolata da un $_POST['user'] e, usata senza controllo, potrebbe contenere qualsiasi codice malevolo come il classico ' or 1 â€".

La variabile $password, venendo codificata dalla funzione hash(), viene neutralizzata dal punto di vista della sicurezza.

A margine, bisogna ricordare che in alcuni casi è utile fare ricorso alle funzioni di sanificazione messe a disposizione a partire da PHP 5.2 in poi, nel caso di numeri o indirizzi email esse offrono già una buona garanzia.

La soluzione risiede nell'uso dei prepared statement che ci garantiscono un miglioramento della sicurezza e anche delle buone performance di esecuzione, in particolare nel caso di operazioni ripetute.

Generare la query con prepared statement

Il primo passo per utilizzare i prepared statement sarà quello di preparare la nostra query sostituendo le due variabili con dei segnaposto (placeholder) che verranno valorizzati in fase di binding:

$query = $mysqli->prepare("SELECT * FROM login WHERE user = ? AND password = ?");

La separazione fra la preparazione dell'SQL e i dati ci permette di avere una protezione rispetto alle SQL injection, infatti i dati provenienti dall'utente verranno gestiti al di fuori dell'istruzione SQL.

A livello di sintassi si deve registrare l'assenza dei delimitatori attorno al parametro: in questo caso pur trattandosi di stringhe non è necessario delimitarle, infatti l'associazione con il tipo di dato verrà fatta in fase di binding.

Associazione parametri-variabili

Il passaggio successivo sarà l'associazione tra il placeholder e la variabile:

$query->bind_param('ss',$user,$password);

Il metodo bind_param accetta due valori: il primo è il tipo di dato e può avere i seguenti valori:

Valore Descrizione
"s" Corrisponde a variabili associate al tipo di dato stringa.
"i" Corrisponde a variabili associate al tipo di dato numeri interi.
"d" Corrisponde a variabili associate al tipo di dato numeri double.
"b" Corrisponde a variabili associate al tipo di dato BLOB, formato binario.

Cosa succede se il valore della variabile non corrisponde con il tipo di dato dichiarato? Viene ripulita. Quindi se la mia variabile avesse come bind il tipo "i", numero intero, e il contenuto della variabile fosse "test", il valore inserito sarebbe 0, compatibile con quanto atteso in fase di dichiarazione.

Il secondo valore è invece la variabile contenente il dato da utilizzare nella query. Attenzione: non possono essere utilizzati valori statici. Le variabili possono essere valorizzate anche dopo il bind_param, a patto ovviamente che siano valorizzate prima dell'esecuzione della query.

Un'altra cosa importante da osservare è che mysqli non supporta i nomi di binding ma solo il binding posizionale, quindi bisogna prestare particolare attenzione all'ordine dei parametri. Nel nostro caso la variabile $user sarà associata al primo parametro della query. Questo limite deve essere considerato come una delle più gravi mancanze di MySQLi.

Eseguire la query

Il terzo ed ultimo passaggio è l'esecuzione vera e propria della query, quindi nel nostro caso:

$result = $query->execute();

A questo punto possiamo valutare il contenuto della variabile $result per sapere se l'operazione di autenticazione è andata a buon fine o meno, potremo quindi procedere con le operazioni di update e delete dei record.

Ti consigliamo anche