Eviter les injections SQL Introduction aux injections SQL

Les injections SQL font partie des vulnérabilités les plus courantes dans les applications web. Si les données en provenance de l'internaute ne sont pas protégées avant d'être insérées dans la commande SQL, il devient possible de modifier considérablement le comportement de la requête.
 

Exemples d'injections SQL

ce décryptage est extrait de la 3e édition de l'ouvrage 'sécurité php 5 et
Ce décryptage est extrait de la 3e édition de l'ouvrage "Sécurité PHP 5 et MySQL" de Damien Seguy et Philippe Gamache, publié chez Eyrolles. © Eyrolles

Les injections SQL prennent naissance dans la construction dynamique de la requête, à l'aide d'une chaîne de caractères : dans cette chaîne, des données de différentes natures sont mélangées avant d'être présentées à la base de données pour qu'elle traite la commande.

Prenons un exemple d'injection. Imaginez un formulaire d'identification : il s'agit d'une simple page web, qui demande un nom d'utilisateur et le mot de passe associé. Ces informations sont ensuite transmises à la base de données pour être comparées avec les listes d'informations des membres du site.
 

Le formulaire fournit deux variables, appelées nom et passe. Nous supposons qu'elles sont utilisées directement dans la requête SQL, sans protection, comme ceci :

<?php
$requete = "SELECT count(*) FROM utilisateurs
WHERE login = '".$_POST['Nom']."' AND
password='".$_POST['passe']."' ";
// reste du script d'identification
?>

Pour réaliser l'injection SQL, il suffit de modifier l'une ou l'autre des variables d'entrée du script pour que la requête change de comportement. Par exemple, nous pouvons utiliser la variable passe comme ceci :

$_POST['passe'] = " ' or 1 = '1 " ;


La requête SQL devient alors :

<?php
$requete = "SELECT COUNT(*) FROM utilisateurs
           WHERE login = 'utilisateur' AND
           password='' or 1 = '1' ";
?>

La condition qui utilise le mot de passe devient toujours vraie, puisque la deuxième partie de la condition OR est toujours vraie. Par conséquent, il suffit que la première partie de la requête soit vraie pour que la clause WHERE réussisse à tous les coups. Il n'y a plus besoin de chercher un mot de passe, mais un nom d'utilisateur. Ces derniers sont généralement faciles à trouver ou à deviner.

Ainsi, pour agrandir encore un peu la faille, nous pouvons aussi utiliser la première partie de la requête :

 $_POST['Nom] = " admin';-- " ;


qui devient alors :

$requete = "SELECT count(*) from utilisateurs
           WHERE login = 'admin'; -- ' AND
           password=''");


Non seulement nous avons pu nous identifier, mais nous sommes même reconnus comme l'administrateur du système et nous avons pu passer sans fournir aucun mot de passe.