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:


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: