Injection sql evitez les failles dans vos requettes

Injection SQL

Introduction

Bonjour !

Je m'appelle François Gingras. J'écris ici mon premier tutoriel. J'ai choisi ce sujet tout simplement parce qu'il m'intéresse. Bon fini le blabla et commençons.

Je vais, dans le tutoriel qui va suivre, vous donner une formation basique sur les attaques SQL, communément appeler Injection SQL. Il est aussi évident que je vais aussi vous montrer comment vous protéger de ce type d'attaque. Vous pouvez voir dans la table des matières le déroulement de l'article. Il est aussi important de savoir que l'injection SQL est plus fréquente dans les scripts ASP ou JSP, à cause de leur configuration par défaut.

L'injection SQL en gros

Une injection SQL consiste à lire, écrire ou même supprimer des données. À première vue, nous pouvons penser que le plus grave est la suppression mais en fait les 3 sont aussi dangereux les un des autres, car si on peu lire, éventuellement, nous pourrons écrire si nous avons accès aux codes administratifs et encore supprimer.

Premier exemple, un administrateur configure mal un formulaire d'authentification. Quand l'utilisateur envoie les données, la requête SQL devrait ressembler à ça :

SELECT uid FROM members WHERE account ='$var_login' AND password='$var_password' 

Si nous prenons par exemple le login Terri et le password Monkey nous avons une requête qui ressemblera à :

SELECT uid FROM members WHERE account='Terri' AND password='Monkey'

Mais si le pirate décide de mettre le login : ' OR 1=1 et la même chose dans le password la requête va devenir :

SELECT uid FROM members WHERE account='' OR 1=1 AND password='' OR 1=1

La requête va prendre le premier compte de la liste (UID 1) et va renvoyer TRUE car 1=1. Alors le pirate va être sur le compte sans avoir le mot de passe. Disons que cet exemple est un peu tiré par les cheveux, mais il illustre bien le principe d'une injection SQL. En passant, le nombre de chance que vous trouviez une situation du genre est de 1 sur 1 000 000. Cet exemple est aussi valide si le pirate veut prendre un compte précis. Il suffit de mettre le login désiré et comme mot de passe : ' OR 1=1 ce qui va renvoyer TRUE.

Injection par SELECT / INSERT / UPDATE

Voici les 3 principales commandes du SQL. SELECT sert à récolter les données, INSERT sert à insérer des données dans une table existante et UPDATE sert à mettre à jour une ou des données entrées. Je ne vais pas entrer dans les détails des formulations des requêtes SQL car ce n'est pas le but de l'article et je considère que vous connaissez déjà le SQL.

SELECT

SELECT est le plus utilisé, car il sert à consulter la base de données. Il sert par exemple à l'authentification d'un compte ou encore à la recherche d'information dans une BD (Base de Données). Le but principal d'une attaque SQL de base est que la requête renvoie vrai même quand c'est faux. Comme l'exemple plus haut, il existe plusieurs façons de rendre une requête vraie. Voici une petite liste :

SELECT * FROM table WHERE 1=1
SELECT * FROM table WHERE 'uuu'='uuu'
SELECT * FROM table WHERE 1<>2
SELECT * FROM table WHERE 3>2
SELECT * FROM table WHERE 2<3
SELECT * FROM table WHERE 1
SELECT * FROM table WHERE 1+1
SELECT * FROM table WHERE 1--1
SELECT * FROM table WHERE ISNULL(NULL)
SELECT * FROM table WHERE ISNULL(COT(0))
SELECT * FROM table WHERE 1 IS NOT NULL
SELECT * FROM table WHERE NULL IS NULL
SELECT * FROM table WHERE 2 BETWEEN 1 AND 3
SELECT * FROM table WHERE 'b' BETWEEN 'a' AND 'c'
SELECT * FROM table WHERE 2 IN (0,1,2)
SELECT * FROM table WHERE CASE WHEN 1>0 THEN 1 END

Référence : Voir chapitre 4

Maintenant, je vais vous montrer un des principaux principes de l'injection SQL : les commentaires. Le caractère # fait que le reste de la requête (après le #) est ignorer par la DB. Les caractères /* et */ mettrons tout ce qu'il y a entre les 2 en commentaire. Par exemple, vous entrez le login : 'Terri'#

SELECT * FROM membres WHERE account='Terri' #  ' AND password='$var_password'

Alors il va prendre le compte Terri en ignorant le mot de passe. C'est encore une injection plutôt rare. J'ai oublié de mentionner que les attaques SQL demandent de la patience et de la persévérance mais je ne suis pas ici pour vous montrer comment démolir un site, mais plutôt pour vous protéger en les évitants.

Avec de l'imagination et une bonne connaissance du SQL vous pouvez récupérer le compte et le mot de passe de l'administrateur si le site est mal protégé. Mais comme je l'ai dit plus haut ce n'est pas facile du tout, au contraire, car la plupart des sites sont bien protégés.

Je vais maintenant passer au INSERT et par la suite le UPDATE.

INSERT

Une requête INSERT est faite pour ajouter des données dans une table existante. Les cas d'injection par INSERT sont plus rares mais il en existe quelques uns. Par exemple une requête INSERT peut ressembler à cela :

INSERT INTO membres (login,password,nom,prenom,email,level) VALUES ('$login','$password','$nom','$prenom','$email','$level')

Si le pirate écrit, dans le champ "email", le code suivant : monemail@monsite.com', '1'# la requête deviendra :

INSERT INTO membres (login,password,nom,prenom,email,level) VALUES ('Terri','MonPass','Terri','Terri','monemail@monsite.com','1' # ','$level')

Alors le pirate aura le level 1 qui peut vouloir dire, par exemple : 1=Administrateur, 2= Modérateur et 3=Utilisateur.

Le problème de ce type d'attaque c'est qu'il faut savoir comment est construite la requête SQL. C'est pour cela que ce genre d'attaque est plus présent dans les systèmes pré faits où le code source est public. Il existe des méthodes pour réussir à reconstruire la requête SQL, mais ce n'est pas encore le but de l'article.

UPDATE

Les requêtes UPDATE sont faites pour mettre à jour des données déjà présentes dans la DB. Les injections UPDATE sont encore moins présentes que les injections INSERT, mais ça existe.

Nous pouvons trouver des requêtes du genre quand il est temps de changer les informations du compte (mot de passe, email, etc..). Alors une requête pourrait ressembler à cela :

UPDATE membres SET password='$var_pass',nom='$var_nom',email='$var_email' WHERE id='$id' 

Ici par exemple nous pourrions changer une valeur que nous ne sommes pas supposé changer. Par exemple, si nous inscrivons dans le champ du mot de passe le code suivant : ',level='3 le code deviendrait le suivant.

UPDATE membres SET password='',level='3',nom='$var_nom',email='$var_email' WHERE id='$id'

Alors le pirate deviendrait administrateur du site en question. C'est sur que cet exemple est encore tiré par les cheveux car il est rare qu'un site accepte un compte sans mot de passe. Il serait mieux de prendre le champ nom ou encore d'écrire quelque chose de bidon dans le champ avant de faire l'injection. Je vous laisse imaginer les possibilités.

Je ne voie pas vraiment l'intérêt de s'attarder encore plus sur l'UPDATE car les cas de faille UPDATE sont très rares et encore plus dur à trouver.

Comment se protéger

Il est certain que la protection à 100% contre les injections SQL est quasiment impossible si ça ne l'est pas. Mais je vais quand même vous montrer quelques trucs pour éviter se genre de failles qui peuvent vous faire perdre beaucoup.

Premièrement, le plus important, filtrer les variables dans les formulaires. Moi personnellement j'utilise une fonction PHP qui me permet de savoir s'il y a un espace ou tout autres caractères spéciaux non désirés. Il est aussi important de préciser que si vous protéger votre formulaire par une fonction JavaScript un pirate va recopier votre formulaire et exploiter en local rien de plus facile, alors à ne pas faire.

Il existe aussi la commende 'htmlentities' qui convertit tous les caractères éligibles en entités HTML. Ce qui empêche les attaques Injection et XSS (Cross Scripting) peut être le sujet d'un autre tutorial.

Mais comme je l'ai dit précédemment, les webmasters ne sont pas stupides, ils vont protéger leur site le mieux possible, alors ne vous attendez pas a trouver une faille SQL en 2 temps 3 mouvements.

Conclusion / Référence

Pour conclure ce tutoriel, il est aussi bon de savoir les autres sortes de failles car si vous n'avez aucune faille SQL il se peut que vous aillez plusieurs failles de types différents. Le pirate ne va pas juste chercher les failles SQL mais va aussi tenter de BruteForcer votre FTP par exemple. Je vous laisse sur cette conclusion, peu rassurante, en vous disant qu'il faut mieux filtrer 2 fois les variables plutôt qu'une.

Référence :
http://www.phpsecure.info/v2/article/InjSql.php

A voir également
Ce document intitulé « Injection sql evitez les failles dans vos requettes » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous