Mis à jour le mercredi 8 mars 2017
  • 4 heures
  • Facile

L'injection SQL

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Explication

L'injection SQL est une méthode d'attaque très connue. C'est un vecteur d'attaque extrêmement puissant quand il est bien exploité. Il consiste à modifier une requête SQL en injectant des morceaux de code non filtrés, généralement par le biais d'un formulaire.

Euhhh... J'ai pas tout saisi...

Pas de panique, je vais illustrer tout ça avec des exemples ! Voilà une requête SQL des plus basiques, qui permet la connexion à un espace membre :

<?php

// On récupère les variables envoyées par le formulaire
$login = $_POST['login'];
$password = $_POST['password'];

// Connexion à la BDD en PDO
try { $bdd = new PDO('mysql:host=localhost;dbname=bdd','root',''); }
catch (Exeption $e) { die('Erreur : ' .$e->getMessage())  or die(print_r($bdd->errorInfo())); }

// Requête SQL
$req = $bdd->query("SELECT * FROM utilisateurs WHERE login='$login' AND password='$password'");

?>

La requête va aller chercher dans la table "utilisateurs" une entrée où le pseudo est égal à $pseudo et où le mot de passe est égal à $password. La faiblesse de ce code se trouve dans le fait que l'on peut envoyer n'importe quoi par le biais du formulaire, y compris des morceaux de code. Par exemple, imaginez qu'un utilisateur (pour une raison x ou y) décide de mettre en login "jean' #" et laisser le password vide. Notre requête deviendrait donc :

<?php

$req = $bdd->query("SELECT * FROM utilisateurs WHERE login='jean' # AND password=''");

// Qui sera interprété de la façon suivante

$req = $bdd->query("SELECT * FROM utilisateurs WHERE login='jean'");

?>

Comme vous le savez, le symbole # permet de faire un commentaire en PHP. Tout ce qui suit ce symbole est donc considéré par PHP comme un commentaire et n'est pas pris en compte dans la requête SQL. Pour faire simple, grâce à cette injection l'utilisateur va pouvoir se connecter à n'importe quel compte sans connaitre son mot de passe. C'est embêtant, vous l'admettez... :-°
Il existe bien d'autres façons d'injecter du code SQL, mais comme je l'ai signifié auparavant je ne suis pas là pour vous apprendre à exploiter des failles mais bien pour vous montrer les failles existantes, vous montrer le danger qu'elles représentent et vous apprendre à vous en protéger efficacement ! Voilà juste pour info quelques autres injections utilisées par les hackers pour arriver à leurs fins :

  • Les conditions toujours vraies comme 1 = 1

SELECT * FROM admin WHERE login='' OR '1'='1' AND pass='' OR '1'='1'
  • Les liaisons entre les tables

SELECT login, password FROM admin WHERE login='' UNION SELECT login, password from admin # ' and password='$password'
  • Outfile

SELECT login, password FROM admin WHERE login='' OR 'X'='X' INTO OUTFILE '../../www/file.txt' #' AND password='$password'";

Comment s'en protéger

Comme vous avez pu le remarquer, les injections SQL bien utilisées peuvent être redoutables ! Mais heureusement pour nous, il est très simple de s'en protéger (surtout avec PDO). Il suffit d'utiliser des requêtes préparées. Notre requête devient donc :

<?php

// On récupère les variables envoyées par le formulaire
$login = $_POST['login'];
$password = $_POST['password'];

// Connexion à la BDD en PDO
try { $bdd = new PDO('mysql:host=localhost;dbname=bdd','root',''); }
catch (Exeption $e) { die('Erreur : ' .$e->getMessage())  or die(print_r($bdd->errorInfo())); }

// Requête SQL sécurisée
$req = $bdd->prepare("SELECT * FROM utilisateurs WHERE login= ? AND password= ?");
$req->execute(array($login, $password));

?>

Et voilà, encore une faille de protégée ! :magicien:

Exemple de certificat de réussite
Exemple de certificat de réussite