Eviter les injections SQL Commandes préparées pour se prémunir contre les attaques par injections SQL

La technique précédente utilisait un concept important : la séparation de la commande et des valeurs. Les commandes préparées portent cette technique encore plus loin.

On commence par demander au serveur SQL de préparer la requête, sans lui donner les valeurs qui seront utilisées. Puis, on indique les valeurs sur lesquelles le serveur doit exécuter la requête. Voici à quoi ressemble l'enchaînement des actions en PHP avec PDO. L'objet $dbh est une connexion à une base de données, qui reconnaît les commandes préparées : c'est le cas de PostGreSQL, Oracle, IBM DB2, SQLite et de bien d'autres.

<?php
// séquence de connexion
$stmt = $dbh->prepare("INSERT INTO REGISTRY (nom, valeur) VALUES (:nom, :valeur)");
$stmt->bindParam(':nom', $nom);
$stmt->bindParam(':valeur', $valeur);

$valeurs = range('a', 'z');
foreach($valeurs as $valeur => $nom) {
// insertion d'une ligne
$stmt->execute();
}
// séquence de déconnexion
?>

Lors de la préparation de la commande, les variables sont identifiées par leur nom. Elles sont ensuite remplies par de vraies valeurs à l'aide des appels à bindParam(). Cette fonction prend le nom de la variable dans la requête SQL et sa valeur stockée dans une variable PHP.

Cette technique est la plus sûre qui soit pour la manipulation de données. Cependant, toutes les interfaces de bases de données n'en disposent pas ; dans ce cas, il faudra utiliser la protection des valeurs présentée dans les sections précédentes.

Toutefois, les commandes préparées ne sont pas totalement sûres. Leur sécurité repose sur la séparation entre la commande et les valeurs, ainsi que sur le type de données qui est imposé à la variable. Certains types de données ne peuvent pas être compilés à ce stade et laissent passer des possibilités d'injection. À l'heure actuelle, cela reste néanmoins la meilleure défense.

Attention

Les commandes préparées ont un impact non négligeable en termes de performances, surtout quand la requête n'est utilisée qu'une seule fois. Non seulement le code PHP est bien plus long, mais en plus la séparation de la préparation et de l'exécution coûte un peu plus cher au serveur SQL. Ces coûts sont uniques et il est possible de réutiliser une commande préparée plusieurs fois dans le même script PHP, sans avoir à la préparer plus d'une fois. Dans ce cas, le coût total de la requête va diminuer.