Eviter les injections SQL Fonctions et caractères à éviter pour contrer les injections SQL

Pourquoi faut-il éviter addslashes() ?

 Il est courant de voir la fonction addslashes() utilisée pour mettre en place la protection des valeurs qui seront introduites dans une requête SQL. En fait, c'est exactement la fonction qui est utilisée par magic_quotes_gpc.

Cette fonction ajoute des barres obliques inverses devant les caractères apostrophe ', guillemet ", NUL \0 et barre oblique inverse \.

La sécurisation de ces caractères est primordiale pour protéger une requête SQL contre les injections, mais elle n'est pas suffisante. Parmi les limitations de addslashes(), on peut noter qu'elle ne protège pas tous les caractères, comme les parenthèses (), _ (souligné, ou underscore) et le signe %, pourcentage. De plus, elle ne prend pas en compte les jeux de
caractères utilisés par la base de données, ce qui limite considérablement son utilité.

Certes, addslashes() vaut mieux que pas de protection du tout. Cependant, elle doit être remplacée par les fonctions de protection adaptées aux technologies qui sont utilisées. MySQL et PostGreSQL proposent leurs fonctions particulières, mysqli_real_escape_string() et pg_escape_string().


Clause LIKE et addcslashes()

Les caractères spéciaux à surveiller ne se limitent pas aux séparateurs de chaînes ' et ". Il faut aussi surveiller les caractères jokers utilisés dans les expressions de recherche. Il y a notamment les caractères souligné _ et pourcentage %.

L'opérateur LIKE est très pratique pour réaliser des recherches simples ou pour appliquer un premier critère de sélection sur des données. Le signe souligné remplace un caractère unique tandis que le signe pourcentage remplace n'importe quelle quantité de caractères.

Les fonctions de protection ignorent ces deux caractères, qui n'ont pas d'autre signification particulière en dehors de leur utilisation avec LIKE. Autrement dit, le script suivant est vulnérable à une injection :

<?php 
  $_GET['prefixe'] = "%e";
  $res = mysqli_query($mid, 'SELECT mot FROM dictionnaire WHERE mot LIKE
  ?"'.mysqli_real_escape_string($mid, '$_GET["prefixe"]').'%" ');
?>


mysqli_real_escape_string() ignore le caractère %. Si la table dictionnaire dispose d'un index sur la colonne mot, la clause LIKE va pouvoir l'utiliser et être très rapide.

Avec cette injection toutefois la requête ne peut plus utiliser l'index et tente une analyse complète de la table pour rechercher tous les mots qui contiennent la lettre e. L'exécution est donc beaucoup plus lente que prévu.

Pour se prémunir contre ce type d'injection, il faut protéger les caractères souligné et pourcentage en les préfixant avec une barre oblique inverse. Le plus simple est de faire un remplacement de ces deux caractères avec str_replace ou bien preg_replace(). Cependant, PHP recèle une de ces fonctionnalités cachées : addcslashes(). Cette fonction ajoute une barre oblique inverse aux caractères qui lui sont indiqués en deuxième argument :

<?php
  $_GET['prefixe'] = "%e";
  $tmp = mysqli_real_escape_string($mid, '$_GET["prefixe"]');
  $tmp = addcslashes($tmp, "%_");
  $_CLEAN['prefixe'] = $tmp;
  $res = mysqli_query($mid, 'SELECT mot FROM dictionnaire WHERE mot LIKE "'.$tmp.'%" ');
?>