Astuces ⇒ PHP facebook twitter youtube

Protéger un  site web ⇒ & Attaque de type SQL injection



Exemple de reqûete :
 

Code:
mysql_query("SELECT * FROM users WHERE login = 'ahmed';");

Cette requête sélectionne l'utilisateur (extrait de la table "users") dont le login est "ahmed". "SELECT *" signifiant qu'on sélectionne tous les champs de cette table. L'exemple ci-dessous est une attaque de type SQL injection afin de récuperer un mot de passe, c'est l'attaque la plus courante. Ma page contient un formulaire d'identification utilisateur classique où l'on entre un identifiant et un mot de passe. La requête associée à ce formulaire permettant de vérifier que les login / password entrés sont valides par rapport à notre base de données serait :
 

Code:
mysql_query("SELECT * FROM users WHERE utilisateur = '$login' AND motdepasse = '$password'");

Cette requête aurait pour effet de sélectionner l'utilisateur en question si le nom d'utilisateur ET le mot de passe entrés sont dans notre base de données. Si l'un des deux est erroné, la requête ne renverra aucun résultat.

L'attaque en question

Sachant que dans mon exemple la variable $login contient ce que j'ai tapé dans mon premier champ de texte et que la variable $password contient ce que j'ai tapé dans le deuxième champ de texte (le mot de passe), voici ce qui arrivera si j'entre le code suivant dans le premier champ Identifiant (ou login) : ' OR 1=1"); // , la requête est :
 

Code:
mysql_query("SELECT * FROM users WHERE utilisateur = '' OR 1=1"); //' AND motdepasse = '$password'");

Et elle permettrait certainement d'identifier l'utilisateur avec succès, car la requête est vraie si un utilisateur "" existe OU si 1=1. Comme l'utilisateur vide n'existe pas, mais que 1 est égal à 1, alors la requête est vraie et valide. Donc, en ajoutant ce code, on force à croire que n'importe quelle requête est vraie. Le signe "//" signifiant un commentaire en PHP, le reste du code n'est pas interprété, il est rendu inutile. Et vous voilà avec un accès à la base de données ! Ceci est l'exemple le plus simple, il en existe bien d'autres qui permettent de véritablement prendre le contrôle d'un serveur en se faisant passer pour root ou l'administrateur. Les possibilités sont malheureusement nombreuses. Nous ne les développerons pas.

 

Comment se protéger des attaques par injection SQL ?

 


Pour prévenir ces attaques, il faut connaître la programmation. Si celle-ci est bien réalisée, les attaques ne sont plus possibles. Voici quelques conseils :

  • - Évitez d'utiliser un compte ayant tous les pouvoirs pour l'exécution de votre serveur SQL.
  • - Supprimez les fonctions que vous n'utilisez pas telle que : master..xp_cmdshell, et de manière générale toutes celles commencant par "master..xp".
  • - Vérifiez les entrées utilisateurs telles que les champs de texte. Vérifiez aussi que les nombres attendus soient bien des nombres avec une fonction telle que IsNumeric() par exemple.
  • - Vérifiez aussi à bien filtrer les paramètres des URL qui sont ajoutables manuellement.
  • - Utilisez les caractères et fonctions d'échappement telles que AddStripSlashes() en PHP, voyez les caractéristiques de la fonction et, en général, les documentations de vos languages de programmation pour plus d'informations. Cela empêchera l'entrée utilisateur du caractère ' en l'échappant à l'aide d'un slash le précédant.
  • - Empêchez d'une manière générale certaines séquences d'entrées utilisateurs telles que ";", "insert", "select", "//", "--", etc.
  • - Limitez le nombre de caractères qu'un utilisateur peut entrer dans un champ de texte, car ceci peut fort bien lui compliquer la tâche.
  • - Attention à ce que vous mettez dans les cookies, car un mot de passe (même crypté en md5) est vite trouvé par une attaque de ce type. Par la suite, un remplacement de cette valeur dans le cookie évite à l'attaquant une attaque de type brute force ; c'est donc un joli cadeau.


 

Application concrète

La méthode la plus simple est de filtrer toutes les variables en appliquant les filtres php comme ceci :
 

Code PHP:
 function anti_injection$user$pass ) {

  # on regarde s'il n'y a pas de commandes SQL

    $banlist = array (

      "insert""select""update""delete""distinct""having""truncate",

        "replace""handler""like""procedure""limit""order by""group by" 

          );

            if ( eregi "[a-zA-Z0-9]+"$user ) ) {

              $user trim str_replace $banlist''strtolower $user ) ) );

                } else {

                $user NULL;

                  }

  

                  # on regarde si le mot de passe est bien alphanumérique

                    # on utilise strtolower() pour faire marcher str_ireplace()

                    if ( eregi "[a-zA-Z0-9]+"$pass ) ) {

                      $pass trim str_replace $banlist''strtolower $pass ) ) );

                        } else {

                        $pass NULL;

                          }

  

                          # on fait un tableau

                            # s'il y a des charactères illégaux, on arrête tout

                            $array = array ( 'user' => $user'pass' => $pass );

                              if ( in_array NULL$array ) ) {

                                die ( 'ERREUR : Injection SQL détectée' );

                                  } else {

                                  return $array;

                                    }

                                    } // ##########

  $login anti_injection ($_POST['pseudo'],$_POST['pass']); // on lance la fonction anti injection

  $password $login['pass']; // on recupère le pass

  $password=md5($password); // on met le pass en md5

  $pseudo $login['user']; // on recupère le pseudo

?>

Changer le fond
Oregionale Skin
7astuces
Sélectionnez un Fond (11)
7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces
Fond de contenu
7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces 7astuces