Comment éviter les injections SQL en PHP?

Si l’entrée utilisateur est insérée dans une requête SQL, l’application devient vulnérable à l’injection SQL, comme dans l’exemple suivant :

$age = $_POST['age']; 

mysql_query("INSERT INTO `person` (`age`) VALUES ('$age')");

C’est parce que l’utilisateur peut saisir quelque chose comme '20') ; DROP TABLE person;--, et la requête devient :

INSERT INTO `person` (`age`) VALUES('20'); DROP TABLE person;--')

Que peut-on faire pour éviter que cela ne se produise ?

Pour utiliser une requête paramétrée, vous devez utiliser soit Mysqli, soit PDO. Pour réécrire votre exemple avec mysqli, nous aurions besoin de quelque chose comme ceci.

<?php
$mysqli = new mysqli("server", "username", "password", "database_name");

$age = $_POST["age"];
$stmt = $mysqli->prepare("INSERT INTO person (age) VALUES (?)");
// "s" signifie que la base de données attend une chaîne de caractères
$stmt->bind_param("s", $age);
$stmt->execute();

La fonction clé sur laquelle vous voudrez vous documenter est mysqli::prepare.

En plus, vous pouvez trouver plus facile de passer à un niveau d’abstraction supérieur avec le PDO.

1 « J'aime »

Je vous recommande d’utiliser PDO (PHP Data Objects) pour exécuter des requêtes SQL paramétrées.

Non seulement cela protège contre les injections SQL, mais cela accélère également les requêtes.

Et en utilisant PDO plutôt que les fonctions mysql_, mysqli_, et pgsql_, vous rendez votre application un peu plus abstraite de la base de données, dans le cas où vous devriez changer de SGBD.

1 « J'aime »

Utiliser PDO et les requêtes préparées. Voici un exemple simple:

$stmt = $conn->prepare("INSERT INTO person VALUES(:id, :name, :age)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->bindValue(':age', $age);
$stmt->execute();
1 « J'aime »

En utilisant cette fonction PHP mysql_escape_string(), vous pouvez obtenir une excellente prévention de manière rapide.

Par exemple :

SELECT * FROM person WHERE age = '".mysql_escape_string($age)."'

mysql_escape_string - Échappe une chaîne pour l’utiliser dans une requête mysql

Pour plus de prévention, vous pouvez ajouter à la fin.

LIMIT 1

Finalement, vous obtenez :

SELECT * FROM person WHERE age = '".mysql_escape_string($age)."' LIMIT 1
1 « J'aime »