Catégories : PHP

Comment se protéger des injections SQL ?

« Injections SQL », voilà un mot lourd. C’est parfait, les résultats de cette technique de hacking peuvent être très lourdes aussi ! Nous allons voir dans ce tutoriel à quel point protéger votre base de données MySQL contre les injections SQL est important, et nous verrons le strict minimum à faire en PHP pour cela.

 

Pourquoi protéger ses requêtes contre les injections SQL ?

La réponse est simple : pour éviter de se faire hacker. Et par hacker, on parle de la copie et la suppression intégrale de toutes vos données.

Non non, ce n’est pas une exagération, c’est vraiment ce que l’on peut faire grâce à une injection SQL. Cette méthode consiste à s’incruster dans un enregistrement dans la base de données pour arrêter la requête avec un point virgule « ; » puis en effectuer une nouvelle.

Exemple d’injection SQL fatale

D’abord, plaçons le contexte sur une chose vraiment très simple : un champ de recherche. Nous avons en effet un champ pour rechercher une liste d’articles de blogs se trouvants dans la table article. Ce champ envoi une requête POST avec le paramètre search. Voici la requête la plus basique qui soit :

$sql = "SELECT `id`,`title` FROM `article` WHERE `title` LIKE '%". $_POST['search'] ."%'";

Donc, si on saisit la recherche « php », la requête SQL ne posera pas de problème.

SELECT `id`,`title` FROM `article` WHERE `title` LIKE '%php%'

Maintenant, si on rentre la recherche suivante « a’; DELETE * FROM article; ». La requête donnera ce qui suit :

SELECT `id`,`title` FROM `article` WHERE `title` LIKE '%a'; DELETE * FROM article;%'

Et voilà, l’intégralité de vos articles ont été supprimés. Pourquoi ?

Le point virgule dans une requête SQL signifie la fin d’une commande. Si celle-ci a correctement été exécutée, on passe à la suivante.

Ainsi, la requête SQL générée exécute trois commandes :

  1. Une recherche sur les articles pour récupérer tous les articles qui finissent par « a ». Même s’il n’y a aucun résultat de recherche, on passe à la commande suivante.
    SELECT `id`,`title` FROM `article` WHERE `title` LIKE '%a'
  2. Suppression de toutes les lignes dans la table article.
    DELETE * FROM article;
  3. Une commande qui ne pourra pas fonctionner. Les commandes suivantes ne seront pas exécutées ; mais les précédentes oui.
    %'

Même si le hackeur ne connaît pas le nom de votre table, il a tout le temps qu’il veut pour la trouver. Suivant comment est fait votre code PHP, il pourra même s’amuser à afficher la liste de toutes les tables. Donc oui, les injections SQL peuvent être vraiment très dangereuses !

 

Se protéger des injections SQL en PHP

Maintenant que vous savez à quel point les injections SQL peuvent être un fléau, voyons une méthode vraiment très simple pour s’en protéger depuis le PHP. Pour cela, nous allons avoir besoin d’utiliser PDO. Nous vous expliquons comment l’utiliser dans le tutoriel PHP : se connecter à une base de données MySQL.

Les requêtes préparées

Pour se protéger des injections SQL, nous allons donc utiliser la fonction prepare de PDO.

Cette méthode consiste à séparer la requête les valeurs envoyées. Pour la première donnée, on ne va pas envoyer la valeur que l’on veut récupérer, mais une clé temporaire qui commence par deux points « : ». Les valeurs seront un tableau indexé par clés sans le préfixe « : ». Voici une requête préparé pour notre exemple précédent.

$sql = "SELECT `id`,`title` FROM `article` WHERE `title` LIKE '%:search%'";
$data = [
  'search' => $_POST['search']
];
$prep = $conn->prepare($sql);
$result = $prep->execute( $data );

Voici un autre exemple après qu’un utilisateur ait envoyé le formulaire de connexion.

$sql = "SELECT `id` FROM `user` WHERE `email`=:email AND `password`=:password";
$data = [
  'email'    => $_POST['email'],
  'password' => md5($_POST['password'])
];
$prep = $conn->prepare($sql);
$result = $prep->execute( $data );

Il est également possible de ne pas nommer ses clés et d’utiliser des points d’interrogation « ? » à la place. Dans ce cas, le tableau de valeurs n’est pas indexé et l’ordre des données doit correspondre à l’ordre d’apparition des points d’interrogation.

$sql = "SELECT `id` FROM `user` WHERE `email`=?AND `password`=?";
$data = [
  $_POST['email'],
  md5($_POST['password'])
];
$prep = $conn->prepare($sql);
$result = $prep->execute( $data );

 

Notre astuce pour protéger des injections SQL

Comme nous l’avons vu, l’injection SQL est une faille de sécurité vraiment très importante qui peut être fatale à toute votre base de données. Pour s’en protéger au niveau de PHP, vous pouvez utiliser la fonction prepare avec PDO. Il y a bien entendu plein de méthodes complémentaires pour se protéger : restriction des droits, cryptage, vérification manuelle… Pour en savoir plus, nous vous conseillons de vous tourner vers un développeur PHP professionnel grâce à Codeur.com. Le dépôt d’annonce est gratuit et les réponses sont rapides.

Partager