Impedisci SQL injection in PHP

Subodh Poudel 22 giugno 2021
  1. Usa le istruzioni preparate e il PDO per prevenire l’iniezione di SQL in PHP
  2. Usa le istruzioni Prepared con la query parametrizzata per impedire l’iniezione di SQL in PHP
  3. Imposta l’attributo PDO::ATTR_EMULATE_PREPARES su false per impedire l’iniezione di SQL
Impedisci SQL injection in PHP

Introdurremo un metodo per prevenire l’iniezione SQL in PHP utilizzando le istruzioni preparate e PHP Data Objects (PDO). Usiamo PDO per stabilire la comunicazione del database in questo metodo. Questo metodo invia i dati e la query separatamente al server del database, il che impedisce la miscelazione dei dati e del server.

Introdurremo un metodo per impedire l’iniezione SQL in PHP utilizzando le istruzioni preparate e la query parametrizzata. Usiamo mysqli per stabilire la comunicazione con il database in questo metodo. Questo metodo ha un meccanismo di lavoro simile al primo metodo. Il punto di contrasto sono solo le funzioni mysqli che usiamo per prevenire l’iniezione SQL.

Ti mostreremo un esempio di come essere al sicuro dall’iniezione SQL durante l’utilizzo del PDO in PHP impostando l’emulazione delle istruzioni preparate su false.

Usa le istruzioni preparate e il PDO per prevenire l’iniezione di SQL in PHP

Possiamo usare l’istruzione preparata insieme al PDO per prevenire l’iniezione di SQL in PHP. L’SQL injection si verifica quando c’è la combinazione della query e dei dati durante l’invio al database. In questo metodo, non specifichiamo il valore esatto dei dati nell’istruzione SQL. Usiamo invece i segnaposto. A causa di ciò, le istruzioni SQL parametrizzate vengono inviate al server come prima richiesta. Usiamo la funzione prepare() per ottenere questo risultato. Associamo il valore esatto del parametro nella seconda richiesta al server del database. Usiamo la funzione bindValue() per questo scopo. In questo modo inviamo il programma alla prima richiesta e i dati alla seconda richiesta. Se richiediamo i dati insieme ai codici SQL, l’utente può modificare il programma e scrivere codici dannosi. Pertanto, impedisce che i codici SQL dannosi vengano iniettati nel server.

Ad esempio, una tabella utenti contiene i seguenti campi e dati.

+----+-----------+----------+------------+
| id | firstname | lastname | dob        |
+----+-----------+----------+------------+
|  1 | bruce     |  rose    | 1998-02-13 |
|  2 | jeff      |  james   | 2000-03-30 |
+----+-----------+----------+------------+

Crea una variabile $firstname e le assegna il nome bruce. Crea una variabile $sql e scrive una query SELECT * FROM users WHERE firstname =:fname; su di essa.

Non scrivere il valore esatto dei dati per firstname. Utilizza invece il parametro :fname. Usa la variabile $pdo per chiamare la funzione prepare() sulla variabile di query. Sostituisci il valore di :fname con la variabile $firstname. Eseguire l’istruzione con la funzione execute(). Controlla il risultato con la funzione fetch() se le credenziali corrispondono al database. In caso affermativo, visualizza il id, firstname, e il lastname della riga selezionata.

L’esempio seguente mostra l’uso di un’istruzione preparata. Memorizza il valore del campo firstname in una variabile per verificare se la credenziale corrisponde. Se invece la variabile contenesse del codice dannoso, visualizzerebbe il messaggio Le credenziali non corrispondono. Questo perché la funzione ready() accetta solo la query parametrizzata e non consente i dati esatti. La variabile $pdo contiene l’oggetto della connessione al database.

Codice di esempio:

# php 7.*
<?php
$firstname = "bruce";
$sql = "SELECT * FROM users WHERE firstname =:fname ;";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(":fname", $firstname);
$stmt->execute();
if(!$result = $stmt->fetch(PDO::FETCH_OBJ)){
    echo "Credentials do no match";
} else {
    echo"Id: ".$result->id. " Name: ".$result->firstname." ".$result->lastname;
}
?>

Produzione:

Id: 1 Name: bruce rose

Usa le istruzioni Prepared con la query parametrizzata per impedire l’iniezione di SQL in PHP

Possiamo usare l’istruzione preparata insieme alla query parametrizzata per impedire l’iniezione di SQL in PHP. Usiamo l’oggetto della funzione mysqli() per creare una connessione al database. In questo metodo, utilizziamo un punto interrogativo ? come segnaposto dei dati. Usiamo la funzione prepare() come il metodo sopra. Usiamo la funzione bind_param() per associare i dati reali nel segnaposto. Questo metodo segue un meccanismo di lavoro simile al metodo sopra.

Ad esempio, stabilisci una connessione al database creando un oggetto della funzione mysqli() e assegnalo a una variabile $conn. Assegnare con il nome jeff a una variabile $firstname. Crea una variabile $sql e scrivi una query SELECT * FROM users WHERE first name =?;. Usa la variabile $conn per chiamare la funzione prepare() sulla variabile di query. Sostituisci il segnaposto ? con la variabile $firstname. Eseguire l’istruzione con la funzione execute(). Chiama la funzione get_result() per memorizzare il risultato nella variabile $result. Controlla se la riga esiste con la proprietà num_rows e restituisci il messaggio No Rows con la funzione exit() se la condizione fallisce. Chiama il metodo fetch_assoc() e memorizzalo nella variabile $row in un bucle while. Visualizza il id, firstname, e il lastname della riga selezionata.

Codice di esempio:

#php 7.x
<?php
$conn = new mysqli($host, $user, $pwd, $dbName);
$firstname = "jeff";
$sql = "SELECT * FROM users WHERE firstname = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $firstname);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) exit('No rows');
    while($row = $result->fetch_assoc()) {
    echo"Id: ".$row['id']. " Name: ".$row['firstname']." ".$row['lastname'];
}

Produzione:

Id: 2 Name: jeff james

Imposta l’attributo PDO::ATTR_EMULATE_PREPARES su false per impedire l’iniezione di SQL

L’utilizzo di istruzioni preparate in PDO potrebbe non essere sufficiente per impedire l’iniezione SQL se non si impostano correttamente gli attributi PDO. Dovremmo impostare l’attributo PDO::ATTR_EMULATE_PREPARES su false per evitare l’iniezione. Se impostiamo l’attributo su true, il PDO emulerà solo le istruzioni preparate invece di usarle. Pertanto, il sistema sarà vulnerabile all’iniezione SQL.

Ad esempio, creare una connessione PDO al database in una variabile $pdo. Usa la variabile per chiamare la funzione setAttribute(). Imposta l’attributo PDO::ATTR_EMULATE_PREPARES su falso.

Esempio di codice:

#php 7.x
<?php
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
?>
Subodh Poudel avatar Subodh Poudel avatar

Subodh is a proactive software engineer, specialized in fintech industry and a writer who loves to express his software development learnings and set of skills through blogs and articles.

LinkedIn