Empêcher l'injection SQL dans PHP

Subodh Poudel 30 janvier 2023
  1. Utilisez les instructions préparées et le PDO pour empêcher l’injection SQL en PHP
  2. Utilisez les instructions Prepared avec la requête paramétrée pour empêcher l’injection SQL en PHP
  3. Définissez l’attribut PDO::ATTR_EMULATE_PREPARES sur false pour empêcher l’injection SQL
Empêcher l'injection SQL dans PHP

Nous allons introduire une méthode pour empêcher l’injection SQL en PHP en utilisant les instructions préparées et les objets de données PHP (PDO). Nous utilisons PDO pour établir la communication avec la base de données dans cette méthode. Cette méthode envoie les données et la requête séparément au serveur de base de données, ce qui empêche le mélange des données et du serveur.

Nous allons introduire une méthode pour empêcher l’injection SQL en PHP en utilisant les instructions préparées et la requête paramétrée. Nous utilisons mysqli pour établir la communication avec la base de données dans cette méthode. Cette méthode a un mécanisme de travail similaire à la première méthode. Le point de contraste n’est que les fonctions mysqli que nous utilisons pour empêcher l’injection SQL.

Nous allons vous montrer un exemple de comment se protéger de l’injection SQL tout en utilisant le PDO en PHP en définissant l’émulation des instructions préparées sur false.

Utilisez les instructions préparées et le PDO pour empêcher l’injection SQL en PHP

Nous pouvons utiliser l’instruction préparée avec le PDO pour empêcher l’injection SQL en PHP. L’injection SQL se produit lors du mélange de la requête et des données lors de l’envoi à la base de données. Dans cette méthode, nous ne spécifions pas la valeur exacte des données dans l’instruction SQL. Nous utilisons les espaces réservés à la place. Pour cette raison, les instructions SQL paramétrées sont envoyées au serveur en tant que première requête. Nous utilisons la fonction prepare() pour y parvenir. Nous lions la valeur exacte du paramètre dans la deuxième requête au serveur de base de données. Nous utilisons la fonction bindValue() à cet effet. De cette manière, nous envoyons le programme à la première requête et les données à la seconde requête. Si nous demandons les données avec les codes SQL, l’utilisateur peut modifier le programme et écrire des codes malveillants. Ainsi, il empêche les codes SQL malveillants d’être injectés dans le serveur.

Par exemple, une table utilisateurs contient les champs et données suivants.

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

Il crée une variable $firstname et lui attribue le nom bruce. Il crée une variable $sql et écrit une requête SELECT * FROM users WHERE firstname =:fname; dessus.

N’écrivez pas la valeur exacte des données pour firstname. À la place, utilisez le paramètre :fname. Utilisez la variable $pdo pour appeler la fonction prepare() sur la variable de requête. Remplacez la valeur de :fname par la variable firstname. Exécutez l’instruction avec la fonction execute(). Vérifiez le résultat avec la fonction fetch() si les identifiants correspondent à la base de données. Si c’est le cas, affichez le id, le firstname, et le lastname de la ligne sélectionnée.

L’exemple ci-dessous illustre l’utilisation d’une instruction préparée. Il stocke la valeur du champ firstname dans une variable pour vérifier si les informations d’identification correspondent. Si la variable contenait du code malveillant à la place, elle afficherait le message Credentials do no match. En effet, la fonction prepared() ne prend que la requête paramétrée et n’autorise pas les données exactes. La variable $pdo contient l’objet de la connexion à la base de données.

Exemple de code:

# 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;
}
?>

Production:

Id: 1 Name: bruce rose

Utilisez les instructions Prepared avec la requête paramétrée pour empêcher l’injection SQL en PHP

Nous pouvons utiliser l’instruction préparée avec la requête paramétrée pour empêcher l’injection SQL en PHP. Nous utilisons l’objet de la fonction mysqli() pour créer une connexion à la base de données. Dans cette méthode, nous utilisons un symbole de point d’interrogation ? comme espaces réservés des données. Nous utilisons la fonction prepare() comme méthode ci-dessus. Nous utilisons la fonction bind_param() pour lier les données réelles dans l’espace réservé. Cette méthode suit un mécanisme de travail similaire à la méthode ci-dessus.

Par exemple, établissez une connexion à la base de données créant un objet de la fonction mysqli(), et affectez-le à une variable $conn. Affectez avec le nom jeff à une variable $firstname. Créez une variable $sql et écrivez une requête SELECT * FROM users WHERE first name =?;. Utilisez la variable $conn pour appeler la fonction prepare() sur la variable de requête. Remplacez l’espace réservé ? avec la variable $firstname. Exécutez l’instruction avec la fonction execute(). Appelez la fonction get_result() pour stocker le résultat dans la variable $result. Vérifiez si la ligne existe avec la propriété num_rows et renvoyez le message No Rows avec la fonction exit() si la condition échoue. Appelez la méthode fetch_assoc() et stockez-la dans la variable $row dans une boucle while. Affichez le id, le firstname et le lastname de la ligne sélectionnée.

Exemple de code:

#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'];
}

Production:

Id: 2 Name: jeff james

Définissez l’attribut PDO::ATTR_EMULATE_PREPARES sur false pour empêcher l’injection SQL

L’utilisation d’instructions préparées dans PDO peut ne pas être suffisante pour empêcher l’injection SQL si nous ne définissons pas correctement les attributs PDO. Il faut mettre l’attribut PDO::ATTR_EMULATE_PREPARES à false pour empêcher l’injection. Si nous définissons l’attribut sur true, le PDO émulera uniquement les instructions préparées au lieu de les utiliser. Ainsi, le système sera vulnérable à l’injection SQL.

Par exemple, créez une connexion PDO à la base de données dans une variable $pdo. Utilisez la variable pour appeler la fonction setAttribute(). Définissez l’attribut PDO::ATTR_EMULATE_PREPARES sur false.

Exemple de code:

#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