Les injections SQL en théorie
31 août 2008
Par Mickaël - Failles Web - Lien permanent
Dans cet article je vais décrire les injections SQL théoriques. Plus tard nous verrons la pratique, parfois très différente de la théorie.
Le SQL est le langage utilisé pour interagir avec les bases de données. Si vous ne connaissez pas ce langage, je vous conseille d'en apprendre au moins les bases.
Les injections SQL, c'est quoi ? Les injections SQL permettent d'exécuter du code SQL arbitrairement, et ainsi d'agir sur la base de données en visionnant et en modifiant le contenu de celle-ci. Les conséquences peuvent aller jusqu'à la récupération de mots de passe, l'ajout d'un nouvel admin, ou peuvent encore conduire vers une faille PHP.
Les injections SQL, comment ça marche ? Pour permettre une injection SQL, il faut qu'une valeur provienne de l'ordinateur client. Cela est généralement sous la forme d'un formulaire dont l'utilisateur aura malicieusement rempli les champs. Mais les injections peuvent aussi être faites à partir de l'URL, des cookies, ou encore des headers HTTP. Au final, tout ce qui arrive au traitement de la requête SQL et venant de l'ordinateur client peut être considérer comme potentiellement dangereux.
Injection par un champ non protégé L'exemple le plus courant (malheureusement) est celui d'une page de connexion : L'utilisateur est censé donner son identifiant et son mot de passe :
<form action="connexion.php"> Pseudo : <input name="pseudo" /><br /> Passe : <input name="passe" /><br /> <input type="submit" /> </form>
Et voici maintenant le côté PHP :
$pseudo = $_POST['pseudo'];
$passe = $_POST['passe'];
mysql_query("SELECT `mess_bienvenue` FROM `utilisateurs`
WHERE `pseudo`='$pseudo' AND `passe`='$passe'", $link);
Ainsi, un utilisateur "normal" rentrerait Micky et secret comme identifiants et verrait ainsi son message de bienvenue, dans le cas contraire il arriverait sur une page lui disant que les identifiants sont mauvais et qu'il doit réessayer.
SELECT `mess_bienvenue` FROM `utilisateurs` WHERE `pseudo`='Micky' AND `passe`='secret'
Cependant un utilisateur malicieux pourrait entrer Micky'-- comme identifiant. La requête deviendrait ainsi :
SELECT `mess_bienvenue` FROM `utilisateurs`
WHERE `pseudo`=' Micky'-- ' AND `passe`='gniark'
Le -- met en commentaire le reste de la ligne et permet ainsi de se connecter quand le pseudo est Micky et c'est tout. Ainsi on peut se connecter avec n'importe quel utilisateur. Il n'est même pas nécessaire de connaître le pseudo de l'admin puisqu'il suffit de faire
WHERE `pseudo`=' 0' or 1=1-- ' AND `passe`='gniark'
Généralement le premier inscrit est le créateur (=administrateur) du site. On se retrouve donc connecté avec les droits administrateurs en un rien de temps ! Il existe aussi d'autres variantes:
WHERE `pseudo`='a' or 'a'='a WHERE `pseudo`='a' or 1>0
Mais le formulaire de connexion n'est pas la seule zone dangereuse ! Un formulaire de recherche d'utilisateurs par exemple, peut se révéler diabolique. Que pensez vous de ceci :
SELECT `adresse` FROM `utilisateurs` WHERE `nom`='%$recherche%'
Qui pourrait se transformer en
SELECT `adresse` FROM `utilisateurs` WHERE `nom`='%%' order by id-- %'
Ce qui nous affichera la liste complète des utilisateurs. Pas grave, me dites-vous ? Et ceci ?
SELECT `adresse` FROM `utilisateurs` WHERE `nom`='%%' or substring(`passe`,0,1)='a'-- %'
Et alors ? Et bien ça affichera tous les utilisateurs dont le mot de passe commence par un a. Avec quelques connaissances, on arrive ainsi facilement à trouver le mot de passe administrateur, en crypté si vous avez été intelligent. Mais pour le décryptage de MD5, c'est une autre histoire... ;)
Variantes possible Toutes aussi graves, on peut exploiter quelques directives SQL:
LOAD_FILE('/chemin/vers/un/fichier/sensible')
Qui permet de charger un fichier pour remplacer un bout de SQL. Si on fait volontairement planter la requête MySQL, et qu'elle est affichée, on peut ainsi obtenir des fichiers assez sensibles tels que /etc/shadow et autres... Bien sûr si on peut lire un fichier, on peut aussi écrire:
INTO OUTFILE (ou INTO DUMPFILE) /var/www/html/sql.txt
Et le fichier contiendra le résultat de la requête. En y mettant un peu de PHP, on peut réussir un contrôle total... D'où l'intérêt de protéger ses requêtes SQL.
Commentaires
Un blog est un journal personnel en effet mais surtout un lieu dechange et de partage d idees (tout comme je fais actuellement sur le sujet) Bref, Merci pour les tuyaux, cest tres enrichissant.
papillondunord