Pour commencer, lorsque vous ferez une requête SQL avec des données dynamiques, il vous faudra toujours utiliser une fonction ou une méthode pour protéger les données dynamiques.
Petit exemple avec la donnée dynamique ayant pour valeur Dupont. Quant au mot de passe il a été traité par la fonction md5() donc aucun soucis à craindre :

SELECT id FROM user WHERE name='Dupont' AND password='45723a2af3788c4ff17f8d1114760e62';


Dans cet exemple tout fonctionne à merveille mais admettons que la donnée vienne d'un formulaire où le visiteur peut marquer ce qu'il veut ça peut donner ceci :

SELECT id FROM user WHERE name='Dupont' -- ' AND password='45723a2af3788c4ff17f8d1114760e62';


Cette fois, on ne se sera pas contenté de taper Dupont dans le formulaire mais Dupont' -- Et comme on peut le voir la fin de la requête avec la partie avec le AND password est ignorée car indiqué comme commentaire avec les deux tirets de notre donnée dynamique.

S'il s'agit d'un formulaire de connexion alors vous pouvez être sûr que la requête renverra l'id de l'utilisateur même si le mot de passe est incorrect. Vous serez donc logué juste en connaissant le nom de l'utilisateur.
C'est donc pour cela qu'il faut protéger ses données avec une fonction adaptée. Heureusement ça ne sera pas bien difficile.

  • Si vous utilisez mysql_connect() pour vous connecter à votre base de données, alors vous devrez utiliser la fonction mysql_real_escape_string()
  • Si vous utilisez mysqli de façon procédurale, vous utiliserez la fonction mysqli_real_escape_string()
  • Si vous utilisez mysqli de façon orienté objet, vous utiliserez la méthode mysqli::real_escape_string()
  • Si vous utilisez PDO, vous utiliserez la méthode PDO::quote()

A savoir que cette liste est non-exhaustive. D'autres fonctions / méthodes existe pour les autres SGBD.
Ça fait beaucoup j'avoue mais c'est indispensable !
C'est le moment des exemples d'utilisations.

Si vous utilisez mysql_connect() :

$name = mysql_real_escape_string("Dupont' -- ");
$password = md5('truc');
$query = "SELECT id FROM user WHERE name='".$name."' AND password='".$password."'";
echo $query; // SELECT id FROM user WHERE name='Dupont\' -- ' AND password='45723a2af3788c4ff17f8d1114760e62'
$result = mysql_query($query);



Si vous utilisez mysqli de façon procédurale :

$name = mysqli_real_escape_string($link, "Dupont' -- ");
$password = md5('truc');
$query = "SELECT id FROM user WHERE name='".$name."' AND password='".$password."'";
echo $query; // SELECT id FROM user WHERE name='Dupont\' -- ' AND password='45723a2af3788c4ff17f8d1114760e62'
$result = mysqli_query($link, $query);


Si vous utilisez mysqli de façon orienté objet :

$name = $mysqli->real_escape_string("Dupont' -- ");
$password = md5('truc');
$query = "SELECT id FROM user WHERE name='".$name."' AND password='".$password."'";
echo $query; // SELECT id FROM user WHERE name='Dupont\' -- ' AND password='45723a2af3788c4ff17f8d1114760e62'
$result = $mysqli->query($query);


Si vous utilisez PDO :

$name = $pdo->quote("Dupont' -- ");
$password = md5('truc');
$query = "SELECT id FROM user WHERE name=".$name." AND password='".$password."'";
echo $query; // SELECT id FROM user WHERE name='Dupont'' -- ' AND password='45723a2af3788c4ff17f8d1114760e62'
$result = $pdo->query($query);



Il faut savoir que pour éviter les injections SQL, il existe aussi les procédures stockées. Comme ce n'est pas exactement le thème de cet article, sachez pour l'instant que ça existe. Je ferais un tour sur ce point là dans un autre article.
Voilà j'ai presque fini de faire le tour avec la protection des données pour une requête SQL.

Mais il reste encore un point à voir. Il s'agit des Magic Quotes implémentées dans PHP pour éviter un bien grand nombre d'injections SQL mais ça suffit largement pas.
Par ailleurs, même la documentation de PHP l'indique.

Cette fonctionnalité est OBSOLETE depuis PHP 5.3.0 et a été SUPPRIMEE depuis PHP 6.0.0. Nous vous encourageons vivement à ne plus l'utiliser.
Il n'y a aucune raison d'utiliser les guillemets magiques, car ils ne sont plus supportés en PHP. Cependant, ils ont existés, et ont aidé quelques débutants, en le permettant de produire, sans le savoir et involontairement, du code plus sécuritaire. Lorsque vous tombez sur des scripts qui s'appuient sur ce type de comportements, il est recommandé de modifier ce code et de désactiver les guillemets magiques. Pour quelles raisons cette fonctionnalité est apparue? Simplement pour se protéger des injections SQL. Aujourd'hui, les développeurs sont plus conscients des problèmes de sécurité, et adoptent les mécanismes de protections de leur base de données, ou les commandes préparées, au lieu de passer par les guillemets magiques.


Il faut le savoir car c'est important, les magic quotes protège les données GET, POST et COOKIE en ayant un comportement similaire à addslashes().
Alors autant prendre les bonnes dispositions de suite et dire exit aux magic_quotes que l'on soit encore en PHP4 ou PHP5.
C'est donc pour cela que je vous ai préparé une classe permettant de supprimer l'effet des Magic Quotes si l'option est activée ou de ne rien faire si l'option est désactivée.

<?php

/*
  Script réalisé par Besset Francis
  pour Informat'Hic ( http://www.informathic.com )
  Vous pouvez utiliser et distribuer librement ce code
  à condition de laisser le nom du réalisateur du code.
  http://www.informathic.com & http://www.apercite.fr
*/

class MagicQuotes {
  var $exists;

  function MagicQuotes() {
    // Si la fonction existe
    // Sinon cela signifie que vous avez une version inférieure à php4 ou supérieure à php5
    if(function_exists('get_magic_quotes_gpc')) {
      $this->exists = get_magic_quotes_gpc();

      // Si les Magic Quotes sont activées
      if($this->exists) {
        if(isset($_GET)) {
          $_GET = $this->del($_GET);
        }
        if(isset($_POST)) {
          $_POST = $this->del($_POST);
        }
        if(isset($_COOKIE)) {
          $_COOKIE = $this->del($_COOKIE);
        }
      }
    }
  }

  function del($arr) {
    $return = array();

    foreach($arr as $k => $v) {
      // Si la variable est un tableau
      if(is_array($v)) {
        // Alors on rappelle la méthode pour traiter ce tableau
        $return[$k] = $this->del($arr[$k]);
      }
      // Sinon si la variable n'est pas un tableau alors elle est susceptible de contenir des antislash ou quotes ajouté par Magic Quotes (Sybase)
      else {
        // Ce n'est pas un tableau, alors on lui enlève les antislashs ajoutés par Magic Quotes
        $return[$k] = stripslashes($v);
      }
    }
   
    return $return;
  }
}

new MagicQuotes();

?>


Pour l'utiliser il suffit d'insérer le code ci-dessous au début de vos scripts :

<?php
include_once('./class.MagicQuotes.php');
?>


Vous pouvez retrouver cette classe en fin d'article en fichier annexe.
Si vous avez la main sur le fichier de configuration php.ini, recherchez magic_quotes et mettez la valeur à Off.

magic_quotes_gpc = Off


Je souhaite lancer une très grosse alerte sur l'affichage des données pouvant être manipulées par le visiteur, les données contenu dans l'adresse, etc.
Utilisez TOUJOURS la fonction htmlspecialchars() comme ci-dessous :

echo htmlspecialchars($_POST['name'], ENT_QUOTES);


Ceci permettra d'éviter les attaques XSS. Je reviendrais plus en détail, sur ce point dans un prochain article.