Les injections SQL - Principes
Définition
Une injection SQL est un type d'exploitation d'une faille de sécurité d'une application interagissant avec une base de données. L'attaquant détourne les requêtes en y injectant une chaîne non prévue par le développeur et pouvant compromettre la sécurité du système.
C'est un cas particulier d'un type de vulnérabilité plus général qui peut se manifester lorsqu'un langage est imbriqué dans un autre.
Lorsqu'on évoque l'injection SQL, on parle tout le temps de faille dans un site Web, mais il n'y a pas que les sites qui sont touchés par cette faille: n'importe quelle application dialoguant avec une base de données en utilisant des requêtes sur lesquelles l'utilisateur a une influence peut être vulnérable aux injections SQL.
Scénario normal
Dans ce chapitre, on prendra en exemple un serveur web (utilisant PHP) proposant à l'utilisateur de rechercher des livres par leur ISBN (on imagine donc un formulaire de recherche basique, avec un champ où l'utilisateur tape l'ISBN, et un bouton pour lancer la recherche).
Lorsque l'utilisateur valide son formulaire de recherche, une requête HTTP est envoyée au serveur. Sur le serveur HTTP, le script PHP va extraire de la requête HTTP l'ISBN entré par l'utilisateur, et va l'intégrer à une chaîne de caractère contenant une macro de requête SQL. Le script va ensuite se connecter à la base de données, envoyer la requête, et recevoir en réponse la liste des livres qui ont cet ISBN. Pour finir, il va compléter une page HTML avec un tableau montrant les résultats de la recherche, et le serveur HTTP va renvoyer cette page à l'utilisateur.
Par exemple, on imagine le code PHP suivant côté serveur:
<?php {…} //Création de la requête //(en PHP, les entrées des utilisateurs sont dans le tableau $_GET (ou $_POST, selon la méthode utilisée)) $req = "SELECT titre,auteur,synopsis FROM livres WHERE isbn = ".$_GET['isbn']; //Lancement de la requête sur la base de données $stmt = $db->query($req); {...} ?>
Si l'utilisateur entre «12345678» comme ISBN, la requête finale (celle que le serveur HTTP enverra au SGBD (Système de Gestion de Base de Données)) sera:
SELECT titre, auteur, synopsis FROM livres WHERE isbn = 12345678
Entrée non vérifiée
On peut voir ici que l'entrée de l'utilisateur n'est pas filtrée: on se contente de concaténer notre macro (qui est une simple chaîne de caractère) avec ce qu'il a tapé, et on envoie la requête telle quelle au SGBD. C'est la raison qui rend l'injection possible.
On part du principe que l'utilisateur a bien tapé un nombre, mais rien ne l'empèche d'envoyer autre chose. Il peut par exemple mettre un bout de requête SQL pour changer le sens de la requête.
Par exemple, s'il rentre comme ISBN « 1234 OR 1 = 1 », la requête envoyée au SGBD sera:
SELECT titre, auteur, synopsis FROM livres WHERE isbn = 1234 OR 1 = 1
Le sens de la requête a été modifié; le SGBD va donc sélectionner les livres qui ont pour ISBN 1234, et les livres où 1 est égal à 1 (ce qui est tout le temps vrai). Côté utilisateur, cette injection aura donc pour effet de lui afficher tous les livres connus de la base (l'intérêt est ici assez limité, on verra dans le chapitre "Exploitation" des exemples un peu plus intéressants).
Les risques
En utilisant l'injection SQL, n'importe qui peut avoir une porte ouverte sur la base de données utilisée par l'application:
- l'attaquant ne sera pas stoppé ni même détecté, quel que soit le degré de paranoïa dont l'administrateur réseau aura fait preuve lors de l'élaboration de ses règles de firewall, puisqu'il attaquera votre base via votre application WEB, qui a forcément les droits nécessaires pour acceder au SGBD
- l'attaquant n'a pas besoin de connaître de login/pass pour se connecter à la base: votre application WEB les connaît, et c'est elle qui va s'authentifier auprès du SGBD.
- l'injection SQL peut fonctionner quel que soit le langage applicatif utilisé sur le serveur HTTP (PHP, ASP ...) et quel que soit le SGBD utilisé (MySQL, PostgreSQL, Oracle ...).
En exploitant une telle faille, un "pirate" peut avoir un accès plus ou moins limité à votre serveur de base de données, dépendemment des précautions prises lors de la conception de l'architecture de l'application: dans le meilleur des cas, il pourra récupérer l'ensemble des tuples de la table visée par la requête; dans le pire des cas, il pourra voir, modifier et supprimer tout ce qui est contenu dans la base. Dans certains cas, il est même possible de faire exécuter des commandes au serveur hébergeant le SGBD: une fois là, on peut imaginer ce qu'on veut (installation de virus sur le serveur, diffusion de vers dans le réseau, etc.).
Il suffit de regarder les actualités pour se rendre compte que personne n'est à l'abri, même les plus grosses entreprises; quelques exemples:
- Juin 2011
LulzSec vole les informations de millions de comptes SONY - Décembre 2009
Un pirate vole 32 millions de logins / pass à RockYou (entreprise développant des applications flash pour Facebook) - Aout 2009
Un américain et 2 russes sont inculpés pour le vol de 130 millions de numéros de carte de crédit qu'ils allaient revendre - ...