JeuWeb - Crée ton jeu par navigateur
sécurité blind injection sql - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : sécurité blind injection sql (/showthread.php?tid=6955)

Pages : 1 2 3


RE: sécurité blind injection sql - Sephi-Chan - 02-09-2013

La question, c'est : quelle requête as-tu executé pour pouvoir affirmer que intval ne suffit pas à protéger ta requête ?


RE: sécurité blind injection sql - niahoo - 02-09-2013

(02-09-2013, 12:00 PM)hercull a écrit : la variable que je récupère en GET est un nombre puis je utiliser mysql_real_escape_string?

Que te dit la documentation de la fonction ?


RE: sécurité blind injection sql - hercull - 02-09-2013

Justement la et la source de mon problème, personnellement après de longues recherches je ne trouve pas de faille de type injection sql sur mon site mais j'ai utilisé un logiciel "Acunetix Web Vulnerability Scanner 9" qui a scanné mon site en identifiant les différentes failles, j'en ai corrigé certaines et celles ci on disparu des résultats , mais une persiste : 'blind injection sql' au nombre de 5, c'est sa que je souhaite réparer.
Donc rien ne me dit que intval ne suffit pas, la faille viens peut être d’ailleurs notamment de mes requêtes sql faite avec mysql_connect...mysql_query, c'est la raison pour laquelle j'ai sollicité votre aide.

Pour mysql_real_escape_string c'est uniquement pour les type string, donc pour récupérer mon GET qui est un nombre j'utilise intval.

La seul possibilité qu'il me reste est de remplacer mes mysql_q.. par une connexion préparé avec PDO comme vous me l'avez indiqué au dessus , ce que j’essaye de faire.


RE: sécurité blind injection sql - Xenos - 02-09-2013

(je suis peut-être mauvaise langue, mais ne connaissant pas le soft, j'avance une question: se peut-il que ce genre de "faille", inapparente, ne soient juste là que pour pousser à acheter la version payante, qui dit explicite où se trouve la "faille"?)

Le plus simple serait de nous donner l'ensemble des requêtes effectuée (pas le mot de passe de connexion...) car sans les requêtes, je ne vois pas comment on pourrait aider. En tous cas, comme dit par tous les autres, la faille ne peut pas venir d'un intval. (sans rapport: as-tu vérifié ce qui se passe quand le _GET n'est pas défini? ou quand _GET n'est pas un nombre et que donc intval() renvoie 0?)


RE: sécurité blind injection sql - hercull - 02-09-2013

Pour le soft c'est exactement ce que je me suis demandé, seulement j'ai fait un premier scan et la majorité des failles étaient effectivement réelles et j'ai comblé ces erreurs, j'ai ensuite fait un second scan et lors de celui-ci les anciennes failles ou j'avais remédié n'apparaissaient plus, il subsistait pourtant 'blind injection sql' au nombre de 5.
Donc c'est la que j'ai pris au sérieux ces résultats et que je me suis mis à chercher une solution.

voici un extrait de mon code, le reste se répète :

Code :
<?php
session_start();

include('connexion_bdd.php');

if(empty($_SESSION['pseudo'])){
  
    $ID_article_selectionne = intval($_GET['ID']);
    
    $ree = 'SELECT MAX(article_ID) AS dernier_article FROM article';
    $dee = mysql_query($ree);
    $fee = mysql_fetch_array($dee);
    $dernier_article = $fee['dernier_article'];
    
    if($ID_article_selectionne > $dernier_article )
        {
        echo'<script>window.location="index.php";</script>';
        
    }
    else{
      
function get_ip(){
                if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
                }
                elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
                $ip = $_SERVER['HTTP_CLIENT_IP'];
                }
                else{ $ip = $_SERVER['REMOTE_ADDR'];
                }
                return $ip;
                }$ip = get_ip();

    $r = "SELECT * FROM ip WHERE visiteur_ip = '".$ip."'";
    $d = mysql_query($r);
    $row1 = mysql_fetch_array($d);
    
    //on  verifi si l'ip existe deja
    
     if (isset($row1['visiteur_ip'])) {
        
         //si l'ip existe on verifie si le visiteur a deja voter pour l'article
        
         $req_article = "SELECT * FROM ip WHERE visiteur_ip = '".$ip."' AND article_ID = '".$ID_article_selectionne."' ";
         $d= mysql_query($req_article);
         $row1 = mysql_fetch_array($d);
    
     if (isset($row1['ip_ID'])) {
            
             //si il a deja voter on verifi si sa fai moin de 24h ou plus
         $rr = mysql_query("SELECT date_ajout_excelence FROM ip WHERE visiteur_ip = '".$ip."' AND article_ID = '".$ID_article_selectionne."'");
         $dd = mysql_fetch_array($rr);
        
          $date_enregistre = $dd['date_ajout_excelence'];
          $date_actuelle = time();
          $difference = $date_actuelle - $date_enregistre;

            if($difference < 86400)
            {
                //si c'est inferieur a 24h alor on recharge la page et rien ne se passe
              
                    
                     echo'<script>window.location="index.php";</script>';
                    
                
            }
            else
            {
                //sinon on prend en compte le vote et on remet la date a l'heure actuelle
                
                $r2 = mysql_query('SELECT      excelence FROM article WHERE article_ID = '.$ID_article_selectionne.';');  
                $d2= mysql_fetch_array($r2);
                    
                $nbr_recup = $d2['excelence'];
                $nbr_recup_final = $nbr_recup+1;
    
                @mysql_query('Update article SET excelence = '.$nbr_recup_final.' WHERE article_ID = '.$ID_article_selectionne.';');
                @mysql_query('Update ip SET date_ajout_excelence = '.$date_actuelle.' WHERE article_ID = '.$ID_article_selectionne.';');
  
                     echo'<script>window.location="index.php";</script>';
            }
?>
...

Pour la situation ou le GET n'est pas défini non je n'ai rien prévu, et non rien prévu dans le cas ou intval renvoi 0, je 'y avais pas pensé merci pour ces informations, je vais essayer d'y remédier.


RE: sécurité blind injection sql - Myrina - 02-09-2013

Code :
...article_ID = '".$ID_article_selectionne."' ";
article_ID doit être une colonne de type INT, donc pas besoin de mettre de quotes.
Code :
...article_ID = ".$ID_article_selectionne;



RE: sécurité blind injection sql - Xenos - 02-09-2013

Pour la qualité du soft, cela ne veut rien dire Wink
Il suffit de faire un bon soft et d'ajouter une ligne dans le texte de sortie: tu auras beau corriger toutes les failles, la ligne restera (mais je médit un peu là, donc bon).
  • Il n'est pas certain que getIp() renvoie bien une IP. Il faudrait vérifier avec la doc de $_SERVER. (x2, $ip est utilisée deux fois dans deux requêtes)
Je ne vois pas d'autre source possible de problème.

Au niveau du code en général:
  • Je ne comprends pas le fait de tester le MAX(id)... Si tu veux savoir si l'article existe, teste directement:
    Code :
    SELECT 1 FROM table WHERE idArticle=$id LIMIT 1
    Et un num_rows te répondra directement si oui ou non l'article existe (Aparté: le "LIMIT 1" optimise-t-il la requête? C'est à dire que si idArticle est une clef primaire ou unique, savez-vous si MySQL est assez futé pour s'arrêter dès le 1er résultat trouvé au lieu de continuer la recherche?)

  • $idArticle (ou similaire) étant un entier, inutile de l'entourer de guillemets dans tes requêtes (cela allège un peu l'écriture); de plus, comme tu utilises des guillemets double autour de la requête, tu n'es pas forcé de faire "SELECT...".$idArticle."..." un simple "SELECT ... $idArticle..." suffit car PHP fera le remplacement nécessaire (sinon, utilises des apostrophes ' au lieu des guillemets doubles " si tu tiens à isoler la variable du texte de la requête)

  • A plusieurs endroits, tu fais deux requêtes, type "je fais une requête pour récupérer une ligne, je teste si la ligne existe, je fais une nouvelle requête pour lire les données". Mauvaise habitude pour deux raisons: 1) imagine que la ligne "fiche le camp" entre temps, car l'utilisateur a cliqué deux fois très vite sur le bouton de vote, alors le teste sera valide, mais la seconde requête pourrait ne pas marcher 2) Ce n'est pas optimisé.
    Ne fais qu'une seule requête pour récupérer les données, et ensuite si ces données existe, traite-les.

  • Se baser sur l'IP n'est pas terriblement fiable, tu auras peut-être des "faux" votes (des gens qui changent d'IP et revotent) ou des blocages si deux personnes ont la même IP (se baser sur l'IP est déconseillé au niveau d'un site car c'est plus du ressort du réseau que du site). Je n'ai pas de solution miracle à proposer.

  • Echappe les noms de colonne et de tables avec `` (alt+gr & touche 7), comme "SELECT `id`FROM `table` WHERE `id`=$id"; ce sera un peu plus lisible, et cela autorisera l'utilisation d'espaces en noms de colonne (bon, c'est pas obligé, mais je trouve personnellement cela plus clair car les noms de colonnes et de table ressortent immédiatement)

  • La redirection avec <script>window.location=...;</script> est ignoble... La méthode que je conseillerai est plutôt l'utilisation des headers HTTP, dont le code HTTP 302. Là, ton script est un peu mélasseux: il gère les trucs (partie controlleur) comme l'enregistrement du vote, et en même temps, il gère l'affichage (echo())... Sépare les deux: contrôleur d'abord, et ensuite l'afficheur, quitte à faire cela "simplement" en créant un buffer intermédiaire: au lieu d'envoyer directement au navigateur, envoie les données à un buffer (soit une chaîne texte, soit avec une fonction perso type echoBuffer, soit avec ce que la documentation php peut te proposer car je crois que cela existe déjà). Ainsi, tu séparera clairement les deux, et tu pourras utiliser facilement la fonction header() pour définir des cookies, ou rediriger le client Wink



RE: sécurité blind injection sql - hercull - 02-09-2013

Merci pour toutes ces précisions je vais essayer d'en tenir compte à partir de maintenant.

Pour le soft tu as raison il y a toujours une possibilité qu'il falsifie les résultats en les gonflant un peu , mais dans tous les cas je préfère utiliser une méthode qui diminue le risque de possibilité d'injection sql.

Pour le getIp() lorsqu'un utilisateur se connecte avec un navigateur tel que Opéra il se trouve en effet que la chaine récupéré est un code qui ressemble à : 2aaie:55d........., donc dans ce cas je ne récupère pas l'ip, pour les autres navigateur je n'ai pas ce problème pour le moment.
D’ailleurs je me demandais si ce code que je récupéré d’Opéra été fixe ou qu'il changeait à chaque visite sur le site?

Pour le cas de l'identification par l'ip pour savoir si une personne a déjà voté je n'utilise ce procédé que pour les visiteur non inscrit, pour ceux qui sont connectés j'utilise leur id, sa me parait la meilleur solution pour le moment.

Pour les script de redirection il est clair que ce n'est pas ce que je voulais utilisé, mais il se trouve que lors de la mise en ligne de mon site plus aucun ne fonctionnaient (je suis chez 1&1), donc j'ai du recourir à cette alternative, si tu connais une façon de faire fonctionner un header location je suis preneur.

Donc d’après ta lecture de mon code il n'y a pas d'erreur de ma part qui permettrai une injection sql de type blind?

je suis entrain de modifier toutes mes requêtes en passant utilisant PDO et des requêtes préparés, dois je poursuivre ou cela est inutile?


RE: sécurité blind injection sql - julp - 02-09-2013

Je rajouterais :
  • $ip n'est jamais échappée (injection en ajoutant une entête HTTP ?)
  • Pourquoi faire un SELECT pour UPDATE un compteur ensuite quand on peut le faire directement en un unique UPDATE, ce qui permettrait d'ailleurs d'assurer que la valeur n'a pas été modifiée entre le SELECT et l'UPDATE
Si le intval, avec la valeur 0 ou je ne sais quoi, est problématique, il y a toujours moyen de valider avant (filter_var, ctype_digit, etc).

Citation :Pour les script de redirection il est clair que ce n'est pas ce que je voulais utilisé, mais il se trouve que lors de la mise en ligne de mon site plus aucun ne fonctionnaient (je suis chez 1&1), donc j'ai du recourir à cette alternative, si tu connais une façon de faire fonctionner un header location je suis preneur.
Symptôme typique des gens qui :
  • envoient du "contenu" avant les fonctions d'entête (setcookie, header et session_start)
  • ont un environnement de développement où l'output_buffering est à on (cf phpinfo) donc ils ne se rendent même pas compte lors de leur dév qu'ils envoient des trucs au client (puisque PHP met tout en tampon - inutile de compter sur l'output_buffering non plus). Et c'est seulement quand ils passent "en prod" sur un autre serveur (où l'output_buffering est à off) qu'ils s'aperçoivent que ces fonctions ne marchent pas/plus

Et ce n'est pas un ob_start qui viendra à bout d'un BOM.


RE: sécurité blind injection sql - niahoo - 02-09-2013

Ton IP Opera là ce serait pas une IPv6 ?