Xss et injection sql:SQL Injection

From aldeid
Jump to navigation Jump to search

SQL injection

Définition

Le site Wkipedia (http://fr.wikipedia.org) définit l'injection SQL de la manière suivante :

Openquotes.gif
Closedquotes.gif
Une injection SQL est un type d'exploitation d'une faille de sécurité d'une application web, en injectant une requête SQL non prévue par le système et pouvant compromettre sa sécurité.

L'injection SQL présente des points communs et des différences avec le cross-site-scripting :

Point communDifférences
  • L'injection SQL, à l'instar du XSS, consiste à injecter du code par l'intermédiaire de champs de formulaires ou via l'URL dans le but d'exploiter des failles relatives à l'interprétation de chaînes malicieuses.
  • L'injection SQL est plus virulente encore que le XSS dans la mesure où elle est directe (pas d'intervention d'un tierce personne).
  • L'injection SQL met en péril les données stockées sur le serveur (suppression possible de données) alors que le XSS ne permet tout au plus que d'ajouter du code dans les tables (via des forums par exmple).

Les risques liés à l'injection SQL

Les attaques par injection SQL permettent des dommages importants :

  • Outrepasser des authentifications et, par extension, se connecter avec un login sans mot de passe ;
  • Suppression de données dans la base de données ;
  • Modification de contenus ;
  • Etc.

Remarque

Le ficher php.ini contient une directive magic_quotes_gpc qui peut prendre les valeurs On et Off. Si ce paramètre est sur On, les exemples qui suivent ne seront pas réalisables car cette option permet d'ajouter le caractère d'échappement devant les apostrophes.
Image015.jpg

Remarque : Il est préférable de désactiver cette fonction (Off) et de gérer les injections SQL applicativement (voir Bonnes pratiques pour gérer l'injection SQL)

Exemples d'injections SQL

L'exemple suivant montre l'exploitation d'une faille sur une page d'authentification non sécurisée.
La page est codée comme suit :

Image017.jpg


Le résultat fournit produit un simple formulaire de login / password comme le montre la figure suivante :

Cette page affiche un formulaire tant que la combinaison login/mot de passe n'est pas présente dans la table utlisateurs… … et un message de bienvenue pour les utilisateurs authentifiés :
Image019.jpg Image021.jpg

Cette page est vulnérable aux attaques par injection SQL comme le montre l'exemple suivant :

Injection d'une chaîne qui rend la requête toujours vraie Injection d'une chaîne qui permet l'authentification à partir d'un login connu, et sans mot de passe

Login : ' OR 'a'='a
Password : ') OR ('a'='a
Requête :

SELECT username, password
FROM auth
WHERE login= OR 'a'='a'
AND password=md5() OR ('a'='a')

Login : oops'#
Password :
Requête :

SELECT username, password
FROM auth
WHERE login='pilou'#'
AND password=md5()
Image023.jpg Image025.jpg

Remarques :

  • Le caractère '#' permet d'ignorer tout ce qui est à droite de ce symbole. Ainsi, il est aisé de forcer la requête à ignorer le filtre sur le mot de passe.
  • Il semblerait que cet exemple ne fonctionne que si la condition suivante est écrite sur une seule ligne dans le code :
WHERE  username='{$_POST['username']}' AND password=md5('{$_POST['password']}')

Bonnes pratiques pour éviter l'injection SQL

Crypter les mots de passe en base :

Une bonne pratique est de ne jamais stocker les mots de passe "en clair" dans la base de données. Il est indispensable de les encrypter en MD5 :
Image027.jpg
Ainsi, même si la base de données est découverte, les hashes de mots de passe seront inexploitables par l'attaquant.
Lorsqu'un mot de passe est encrypté en MD5, la fonction retourne une chaîne (hash) indéchiffrable. L'authentification s'effectue alors par comparaison des chaînes issues du champ mot de passe du formulaire et en base de données.

Ne jamais retourner le login ou le mot de passe dans des requêtes d'authentification

Eviter de retourner le mot de passe dans les requêtes de vérification des correspondances login/mot de passe. Par extension, bannir les requêtes du type select * from table sur des tables utilisateurs. Dans la mesure du possible, utiliser des requêtes du type :

SELECT 1 FROM utilisateurs

ou

SELECT COUNT(1) FROM utlisateurs

Utiliser la fonction mysql_real_escape_string

La fonction mysql_real_escape_string protège les caractères spéciaux d'une commande SQL.
Par extension, la fonction de purification suivante permet, en une seule ligne de code, de purifier les données issues d'un formulaire :

function sanitize($input){
    if(is_array($input)){
        foreach($input as $k=>$i){
            $output[$k]=sanitize($i);
        }
    }
    else{
        if(get_magic_quotes_gpc()){
            $input=stripslashes($input);
        }       
        $output=mysql_real_escape_string($input);
    }   
   
    return $output;
}

Exemple d'utilisation :

<?php
$_POST = sanitize($_POST);
?>





Cross Site Scripting (XSS)
[Sommaire]
Conclusions