mercredi 13 août 2008

comprendre les injections SQL

Qu' est ce qu' une injection SQL?
Tout d' abord on va preparer le terrain et voir ce qu' est une requête normal.
Nous allons tout le long de cette article travailler avec cette table de 3 champs ( id, pseudo, password ).

Et voila les enregistrement de cette table:

| 1 | alain | pofigljfh |
| 2 | admin | tupacritu |
| 3 | moderateur | mfgpgfkg |
| 4 | boby | mdgdggfkg |
| 5 | janine | fofofofofo |

Et nous allons imaginer cette situation, ou le programmeur à oublié, de filtrer les entrer de la base de donnée et que l' option magic_quote_gpc est a Off dans le php.ini.

$connexion = mysql_connect('localhost','user','motDePasse');

mysql_select_db('injection');

if(isset($pseudo) AND isset($pass))
{
$req = "SELECT pseudo,password FROM `essai` WHERE pseudo='$pseudo' AND password='$pass'";

$res = mysql_query($req);

while($x = mysql_fetch_array($res))
{
echo $x['pseudo']. ' ' .$x['password'].'
'; } }

Donc le script PHP attend un pseudo et un mot de passe, transmis par le formulaire via la method POST, une fois qu' il a le pseudo et le mot de passe il envoie la requête a la base de donné qui elle cherche si dans la table essai si il ce trouve un pseudo et un mot de passe qui correspond a ce que l' utilisateur à rentrer. si elle trouve une correspondance elle l' affiche sinon elle ne renvoi rien du tout.
Donc si l utilisateur est (alain) et a pour mot de passe (pofigljfh) la requête deviendra (en vert c' est ce que rentre l' utilisateur).

SELECT pseudo,password FROM `essai` WHERE pseudo='alain' AND password='pofigljfh'

Et l utilisateur sera authentifié car il y a bien une correspondance dans la table.
Maintenant en sachant que le script ne filtre pas les caractère spéciaux il est facile de déformer la requête.
Regardons cette exemple (en vert c' est ce que rentre l' utilisateur):


SELECT pseudo,password FROM `essai` WHERE pseudo='alain' OR '1'='1' AND password='chaineAuHazard' OR '1'='1'

Le truc c' est que la condition sera toujour vrai puisque , on demande d afficher les champs ou (1 est égal à 1) donc bête et discipliner le programme renverra tout les enregistrements de la base, avec le pseudo et mot de passe de l' administrateur.Voici quelque autre exemple ou l' egalité est toujours vrai:

WHERE pseudo='alain' OR 'a'='a' AND password='chaineAuHazard' OR 'a'='a'
WHERE pseudo='alain' OR 'a'='a' AND password='bloup' OR 'b' between 'a' AND 'c'

Le dernier exemple est aussi valide et oui car on demande les champs ou b est entre a et c.
Aller pour la forme un dernier, on sais que les commentaires en SQL commencent par un # c' est a dire que tout ce qui ce trouve après sera ignorer.Ici on va imaginer que l on connais juste le pseudo de l administrateur du site.
Mise en pratique:


SELECT pseudo,password FROM `essai` WHERE pseudo='admin'#' AND password='bloup'
Donc ici pas besoin du mot de passe puisque le password est mis en commentaire.Donc voila quelque exemple parmis tant d' autre, mais comment sécurisé tous ca?
Avec la fonction mysql_escape_string() ou mysql_real_escape_string() par exemple.
Donc notre script securisé devient:
SELECT pseudo,password FROM `essai` WHERE pseudo='mysql_escape_string($pseudo)' AND password='mysql_escape_string($pass)'
Je ne vais pas passer en revue tout les types d' injection car chaque cas est différent mais les base sont là.

::: conseil

Je ne peut que vous conseiller de mettre séverement à l' épreuve votre site avant de le publier, il ne faut pas oublier que le but premier d' un hacker est de faire planter votre script afin qu' il génère une erreur, vous allez me dire pourquoi ?
C' est tout simplement pour obtenir des informations sur vos bases,vos tables, les noms des champs, la version de mysql etc ...
Protèger chaque variable quand vous le pouvez avec une fonction adapté, vous avez le choix, mysql et PHP disposent de beaucoup de fonctions pour vérifier les types des donnés, échappé les caractère spéciaux etc ...
Rentrer des caractères dans l' url comme %22 %23 %27 %25 %24 %5E %3B %2C %3A %21 %3C %3E et analyser le comportement du script, il ne doit y avoir aucun message d' erreur qui s' affiche, n' oublier pas qu' il est possible de cacher les messages d' erreur avec un @ placer devant le nom d' une fonction ou d' une instruction.D' autre par ne laisser pas trainer des fichiers inutile.
Faite tout ce qui est possible et imaginable pour faire planter votre script !! et corriger les erreurs.

Aucun commentaire: