PRATIQUE ALGO/METHODES 
Expliquez-moi... Les injections SQL
 
Utilisées pour pirater les applications Web dynamiques, les injections SQL compromettent les données stockées sur votre base. Présentation des dangers potentiels et de quelques approches pour les éviter. (14/07/2006)
  Forum

Réagissez dans les forums de JDN Développeurs

Dans le monde de la sécurité Web, les injections SQL sont l'une des plus grandes menaces pour le contenu des sites dynamiques. Mal préparés, les formulaires et requêtes d'un site peuvent donner accès à l'ensemble des données des bases SQL, avec un minimum de manipulation. Le but est donc de nettoyer autant que possible les données qui transitent par le serveur.

Les données dynamiques affichées par un site Web sont tirées d'une base SQL par le biais d'une requête. Celle-ci est lancée soit par une URL particulière, soit un formulaire HTML. Le langage serveur récupère alors ces informations par le biais d'une requête HTTP POST ou GET, les donne à la base SQL, qui établit les données à renvoyer, et les réponses à cette requête. L'idée d'une injection SQL est de tromper le langage serveur en envoyant des données qu'il n'avait pas prévues, mais qui provoquent néanmoins un résultat.

L'injection SQL cherche donc à profiter du manque de traitement des chaînes transportées par la requête POST ou GET. L'exemple typique est celui où le contenu de la chaîne contient un guillemet anglais (") ou une apostrophe droite ('). Si la chaîne est intégrée sans plus de traitement ou de filtrage à la requête SQL, il y a compromission.

Par exemple, pour déterminer si l'utilisateur peut se connecter :

Requête SQL : $req = "SELECT count(*) FROM utilisateurs WHERE identifiant = '{$_GET['identifiant']}'";
Chaîne injectée : nomBidon' OR 'a'='a
Requête SQL complétée de la chaîne : $req = "SELECT count(*) FROM utilisateurs WHERE identifiant = 'nomBidon' OR 'a'='a'";

On voit que la proposition 'a'='a' sera toujours vraie, donc cette requête amènera toujours un count(*) différent de 0, ce qui peut permettre à l'auteur de cette injection de se connecter au site sans même y avoir un compte.

Ce n'est là qu'un court exemple, mais on comprend qu'il est possible, pour des formulaires non traités, de lancer ses propres requêtes SQL : effacer des tables, créer des utilisateurs, récupérer tous les mots de passe... Il devient donc nécessaire de correctement nettoyer le contenu des chaînes reçues, selon les usages que l'on en fait.

Le premier traitement à réaliser consiste à filtrer la chaîne avec le caractère d'échappement SQL, '\', pour toutes les variables en provenance de l'extérieur : en PHP par exemple, $_GET, $_POST, mais aussi $_COOKIE, $_FILES, $_REQUEST... PHP dispose pour cela de la fonction addslashes(). En vérifiera également que les "Magic Quotes" sont désactivées (lire notre article du 13/12/02, point 6).

Autre aspect à vérifier, le type du contenu. Si l'on attend une chaîne, il conviendra de tester avec is_string(). Idem pour les autres types.

Le point fondamental à respecter : il est préférable de n'accepter que les bonnes données, plutôt que de risquer de laisser passer des injections. Utilisez donc toute la puissance de traitement de votre langage serveur avant de lui faire envoyer la requête vers SQL. Par ailleurs, il est de bon ton de stocker les chaînes non traitées avec une certaine convention de nommage, et les chaînes traitées avec une autre (par exemple, un préfixe "nt" pour toute chaîne non-traitée, et "p" pour les chaînes propres). On est ainsi certain de travailler avec les bonnes données, n'importe où dans le code.
 
Xavier Borderie, JDN Développeurs
 
 
Accueil | Haut de page