Partage
  • Partager sur Facebook
  • Partager sur Twitter

sécurité injection sql et query

affichage commande client

Sujet résolu
    10 décembre 2024 à 0:44:43

    Bonsoir,
    suite à plusieurs sujet poster ici ( les doubles connections a une base de donnée sur la même page ) je me renseigne sur les injections sql et la securité

    ( passer de mysqli à pdo par ex ou bien les requêtes préparés)

    Alors voilà sur mon site j'affiche les commandes des utilisateurs selon si leurs  Session email corrrespond as l'email de la base de donnée j'affiche les transactions )

    J'avais 2 connections une en pdo pour la connection et l'affichage du profil et une en mysqli pour l'affiche des commandes.

    J'ai corriger sa pour n'avoir qu'une seule connection en pdo seulemt une chose me chiffonne

    $bdd = new PDO('mysql:host=localhost;dbname=;charset=utf8', '', '');
    if(isset($_SESSION['id']) AND $_SESSION['id'] > 0) {
       $getid = intval($_SESSION['id']);
       $requser = $bdd->prepare('SELECT * FROM membres WHERE id = ?');
       $requser->execute(array($getid));
       $userinfo = $requser->fetch();
    <h1><?php echo _("Mes Commandes"); ?></h1>
                <?php
                
                $result = "SELECT id, payer_name, payer_email, paid_amount, created FROM transactions WHERE payer_email= '".$_SESSION['mail']."'";
                $stmt = $bdd->query($result);
                ?>
                <table>
                	<?php
                if ($stmt->rowCount() > 1) {
                  echo "<thead>".
                        
                        "" . _("<td>ID</td>") . "".
                        "" . _("<td>Nom et Adresse</td>") . "".
                        "" . _("<td>Email</td>") . "".
                        "" . _("<td>Total</td>") . "".
                        "" . _("<td>Date</td>") . "".
                        "</thead>".
                        "<tbody>";
                     while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                      echo "<tr>".
                           "<td>" . $row["id"]. "</td>".
                           "<td>" . $row["payer_name"]. "</td>".
                           "<td>" . $row["payer_email"]. " </td>".
                           "<td>" . $row["paid_amount"]. " </td>".
                           "<td>" . $row["created"]. "</td>".
                           "</tr>";
                    }
    Dois je passer par un prepare et execute sur la partie affichage de commande pour plus de sécurité où c'est bon ainsi ?






    • Partager sur Facebook
    • Partager sur Twitter
      10 décembre 2024 à 1:45:28

      Bonsoir,

      >> Dois je passer par un prepare et execute

       RTFM. La réponse se trouve dans la documentation de la méthode que vous utilisez. => Doc de querry()  

      "Prépare et Exécute une requête SQL sans marque substitutive"

      Note:

      Si query contient des marqueurs de substitution, la requête doit être préparé et exécuté séparément en utilisant les méthodes PDO::prepare() et PDOStatement::execute().

      Donc en résumé, si tu as dans la requête un paramètre variable ou que tu dois effectuer plusieurs fois la requête : tu n'utilises pas querry

      Lecture complémentaire : https://www.julp.fr/articles/2-pdo-mode-d-emploi.html

      PS :  N'utilise pas rowCount() sur une requête SELECT. Voir l'exemple de la doc et cette entrée dans la FAQ.

      • Partager sur Facebook
      • Partager sur Twitter
        10 décembre 2024 à 2:25:42

        Merci d'avoir pris le temps de répondre

        par contre le rtfm étais pas utile les 2 liens ci dessus je les ai parcouru, 

        Pour le rowCount dans le doc il s'utilise bien pour select

        'Quant aux requêtes de type SELECT, c'est vers la méthode query qu'il faut se tourner, qui vous retourne un objet PDOStatement dont nous verrons plus tard l'exploitation. Mais vous savez d'ores et déjà que vous pouvez utiliser ce dernier pour connaître le nombre de résultats retournés via sa méthode rowCount, analogue à mysql_num_rows.' pourquoi M'en parle tu je capte pas ?

        je bloque ici

        payer_email= '".$_SESSION['mail']."'"


        je sais qu'on peut manipuler les Get pour les injections sql , les Sessions égalements ??

        $stmt = $bdd->prepare("SELECT * FROM recipes WHERE payer_email = ?"); 
        $stmt->execute([$_SESSION['mail']]);
        $data = $stmt->fetchAll();

        du coup je devrais faire un code dans se genre la ?

        -
        Edité par lutinjoyeux 10 décembre 2024 à 4:10:05

        • Partager sur Facebook
        • Partager sur Twitter
          10 décembre 2024 à 11:20:15

          > je sais qu'on peut manipuler les Get pour les injections sql , les sessions également ??

          Non mais cette donnée provient bien de l'utilisateur au départ (du $_POST quoi) ? De toute façon, le principe est de ne JAMAIS concaténer/injecter des données [directement] dans une requête SQL.

          > du coup je devrais faire un code dans ce genre là ?

          Oui mais ta précédente surcouche PDO aurait même permis d'écrire :

          $data = $db-&gt;query('SELECT * FROM recipes WHERE payer_email = ?', [$_SESSION['mail']]);
          

          Quant à rowCount, il est déconseillé de l'employer après une requête SELECT, officiellement elle n'était pas prévue pour remplir le rôle de mysql_num_rows (le nombre de lignes renvoyées par un SELECT notamment) mais uniquement de mysql_affected_rows (le nombre de lignes créées/modifiées par un INSERT/DELETE/UPDATE). Le pilote MySQL fait les deux (dans certaines situations ?) mais ce n'est pas valable pour tous les SGBD (PostgreSQL de mémoire) donc n'est pas portable (demain, tu changes de SGBD, ton code pourrait ne plus fonctionner à cause de ce rowCount).

          TL;DR : à éviter, chose qui est en général facile à faire, il y a toujours un moyen de la remplacer, surtout pour la simple et bonne raison qu'elle est souvent très mal employée à la place d'un SELECT COUNT où vous demandez alors un résultat que vous ne parcourez ensuite jamais.

          PS : perso, je ne suis pas fan du fetchAll quand je sais n'attendre qu'au plus une ligne. Un fetch, c'est plus direct, pas besoin d'un tableau intermédiaire, d'autant que tu peux tester dans le même temps si cette ligne existe ou non.

          -
          Edité par julp 10 décembre 2024 à 12:00:33

          • Partager sur Facebook
          • Partager sur Twitter
            10 décembre 2024 à 13:05:21

            D'accord la donnée vient d'un POST de ma page inscription
                        $stmt = $bdd->prepare("SELECT id, payer_name, payer_email, paid_amount, created FROM transactions WHERE payer_email= ?", [$_SESSION['mail']]);
                        $stmt->execute([$_SESSION['mail']]);
                        
                        ?>
                        <table>
                        	<?php
                        if ($stmt->fetch() > 1) {
                          echo "<thead>".
                                
                                "" . _("<td>ID</td>") . "".
                                "" . _("<td>Nom et Adresse</td>") . "".
                                "" . _("<td>Email</td>") . "".
                                "" . _("<td>Total</td>") . "".
                                "" . _("<td>Date</td>") . "".
                                "</thead>".
                                "<tbody>";
                             while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                              echo "<tr>".
                                   "<td>" . $row["id"]. "</td>".
                                   "<td>" . $row["payer_name"]. "</td>".
                                   "<td>" . $row["payer_email"]. " </td>".
                                   "<td>" . $row["paid_amount"]. " </td>".
                                   "<td>" . $row["created"]. "</td>".
                                   "</tr>";

            TL;DR sa correspond a quoi ? c'est un bug comme les les &lt; sont des <
            • Partager sur Facebook
            • Partager sur Twitter
              10 décembre 2024 à 13:26:49

              lutinjoyeux a écrit:

              TL;DR sa correspond a quoi ?

              Bonjour, quand tu ne connais pas quelque chose fait une recherche avec ton moteur de recherche favoris.

              => https://fr.wiktionary.org/wiki/TL;DR

              • Partager sur Facebook
              • Partager sur Twitter
                10 décembre 2024 à 13:57:09

                Non, lutinjoyeux, c'est la requête préparée que tu avais écrite dans ton deuxième message pour du PDO natif ou ce que j'ai écrit pour ta "surcouche"/encapsulation de PDO que tu employais dans tes précédents sujets, pas un mélange des deux comme dans ton troisième message (ce que tu as mis en deuxième argument du PDO::prepare n'a pas lieu d'être).

                > if ($stmt-&gt;fetch() &gt; 1) {

                Si tu (re)prends la doc de PDOStatement::fetch, que retourne-t-elle ? Est-ce qu'une comparaison à un entier fait sens ?

                Ici, pour remplacer le rowCount (dans le besoin de savoir si la requête a renvoyé au moins une ligne), l'idéal serait un do/while après un if d'une tentative de lecture du premier résultat (fetch) :

                if ($row = $stmt-&gt;fetch()) { # ou, si tu préfères : if (false !== ($row = $stmt-&gt;fetch())) {
                    # le code HTML avec les table + thead + tr + th + tbody
                    do {
                        # le même code HTML avec les tr + td
                    } while ($row = $stmt-&gt;fetch());
                    # fermeture des tbody + table
                } else {
                    // la table est vide/la requête n'a rien retourné
                }
                

                Cette approche n'est certainement ni facile à comprendre ni un automatisme pour les débutants. Une autre approche plus courante est fetchAll :

                if ($rows = $stmt-&gt;fetchAll()) {
                    # le code HTML avec les table + thead + tr + th + tbody
                    foreach ($rows as $row) {
                        # le même code HTML avec les tr + td
                    }
                    # fermeture des tbody + table
                } else {
                    // la table est vide/la requête n'a rien retourné
                }
                

                Cependant, il faut savoir que fetchAll, contrairement à fetch où tu récupères une ligne à la fois, copie tout(es les lignes) en mémoire au point potentiellement, quand il y a vraiment beaucoup de données, de dépasser la mémoire que tu peux allouer (cf memory_limit). N'utilisez pas toujours fetchAll ou assurez-vous au moins de contrôler le nombre de lignes retournées par votre requête (ie à défaut, mettez une clause LIMIT/paginez).

                -
                Edité par julp 10 décembre 2024 à 15:10:57

                • Partager sur Facebook
                • Partager sur Twitter
                  10 décembre 2024 à 15:22:38

                  merci pour vos réponse du coup voilà en corriger


                  fetch  je pensai que sa renvoyer une seul ligne ( exemple sur 6 commande sa ne renverrai que la première)

                  effectivement c'est plus claire pour moi  'recupere une ligne à LA fois'


                  $stmt = $bdd->prepare("SELECT id, payer_name, payer_email, paid_amount, created FROM transactions WHERE payer_email= ?");
                              $stmt->execute([$_SESSION['mail']]);
                              
                              ?>
                              <table>
                              	<?php
                              if ($row = $stmt->fetch()) {
                                echo "<thead>".
                                      
                                      "" . _("<td>ID</td>") . "".
                                      "" . _("<td>Nom et Adresse</td>") . "".
                                      "" . _("<td>Email</td>") . "".
                                      "" . _("<td>Total</td>") . "".
                                      "" . _("<td>Date</td>") . "".
                                      "</thead>".
                                      "<tbody>";
                                   while($row = $stmt->fetch()) {
                                    echo "<tr>".
                                         "<td>" . $row["id"]. "</td>".
                                         "<td>" . $row["payer_name"]. "</td>".
                                         "<td>" . $row["payer_email"]. " </td>".
                                         "<td>" . $row["paid_amount"]. " </td>".
                                         "<td>" . $row["created"]. "</td>".
                                         "</tr>";
                                  }
                                  echo "</tbody>";
                              } else {
                                echo "0 results";
                              }
                              $bdd->close();
                  en faite les précedents post sur la pagination , panier et les requêtes et connexion pdo dans un fichier a part db.class.php sont dans un sous dossier par rapport au dossier membre

                  j'imagine que je pourrai tout regrouper et n'avoir qu'un seul fichier a part pour toutes mes requêtes préparer mais je préfère pour le moment attendre avant de tout regrouper car c'est pas ma tasse de thé de tout intégré

                  -
                  Edité par lutinjoyeux 10 décembre 2024 à 15:53:35

                  • Partager sur Facebook
                  • Partager sur Twitter
                    10 décembre 2024 à 15:51:01

                    Ici, il te faut une boucle do/while, pas while sinon tu vas "perdre" la première ligne.

                    > en faite les précedents post sur la pagination , panier et les requêtes et connexion pdo dans un fichier a part db.class.php sont dans un sous dossier par rapport au dossier membre

                    Tu organises tes fichiers comme tu veux, ça n'a pas d'incidence, c'est à ça que sert require.

                    > j'imagine que je pourrai tout regrouper et n'avoir qu'un seul fichier a part pour toutes mes requêtes préparer mais je préfère pour le moment attendre avant de tout regrouper car c'est pas ma tasse de thé de tout intégré

                    Et comment tu ferais tes binds ? En encapsulant la requête préparée dans une fonction ? Pas convaincu par l'approche, tu aurais un script énorme avec toutes les requêtes, ça te fait potentiellement deux fichiers à ouvrir au lieu d'un, pas évident de mettre les 2 en corrélations surtout pour des requêtes utilisées qu'une fois. A la rigueur, pourquoi pas pour des requêtes communes à plusieurs scripts.

                    -
                    Edité par julp 10 décembre 2024 à 15:51:59

                    • Partager sur Facebook
                    • Partager sur Twitter
                      10 décembre 2024 à 16:30:43

                      $stmt = $bdd->prepare("SELECT Count(*), payer_name, payer_email, paid_amount, created FROM transactions WHERE payer_email= ?");
                                  $stmt->execute([$_SESSION['mail']]);
                                  $row = $stmt->fetchColumn();
                                  ?>
                                  <table>
                                  	<?php
                                  do {
                                    echo "<thead>".
                                          
                                          "" . _("<td>ID</td>") . "".
                                          "" . _("<td>Nom et Adresse</td>") . "".
                                          "" . _("<td>Email</td>") . "".
                                          "" . _("<td>Total</td>") . "".
                                          "" . _("<td>Date</td>") . "".
                                          "</thead>".
                                          "<tbody>";
                                      
                                        echo "<tr>".
                                             "<td>" . $row["id"]. "</td>".
                                             "<td>" . $row["payer_name"]. "</td>".
                                             "<td>" . $row["payer_email"]. " </td>".
                                             "<td>" . $row["paid_amount"]. " </td>".
                                             "<td>" . $row["created"]. "</td>".
                                             "</tr>";
                                      }while($row > 0);

                      c'est pas gagner 
                      • Partager sur Facebook
                      • Partager sur Twitter
                        10 décembre 2024 à 16:41:44

                        J'ai donné la solution 2 posts (des miens) plus tôt, il n'y avait que 2 lignes à adapter :

                        • while($row = $stmt-&gt;fetch()) { devenait do {
                        • } (celle qui mettait fin à ce même while) devenait } while($row = $stmt-&gt;fetch());

                        Je n'ai pas parlé de fetchColumn et la requête en elle-même ne nécessitait pas de modifications (elle n'est pas censée fonctionner et avec une fonction d'agrégation sans clause group by tu n'aurais qu'une ligne de résultat).

                        -
                        Edité par julp 10 décembre 2024 à 17:03:46

                        • Partager sur Facebook
                        • Partager sur Twitter
                          10 décembre 2024 à 17:14:57

                          ah oui excusez moi arf

                          echo "<table>".
                                              "<thead>".
                                              "" . _("<td>ID</td>") . "".
                                              "" . _("<td>Nom et Adresse</td>") . "".
                                              "" . _("<td>Email</td>") . "".
                                              "" . _("<td>Total</td>") . "".
                                              "" . _("<td>Date</td>") . "".
                                              "<tbody>".
                                              "<tr>".
                                                 "<td>" . $row["id"]. "</td>".
                                                 "<td>" . $row["payer_name"]. "</td>".
                                                 "<td>" . $row["payer_email"]. "</td>".
                                                 "<td>" . $row["paid_amount"]. "</td>".
                                                 "<td>" . $row["created"]. "</td>".  
                                          }while($row = $stmt->fetch());
                                          "</tr>".
                                          "<tbody>".
                                          "</thead>".
                                          "</table>".;
                          les td aussi je dois les mettres aprés le while ?

                          • Partager sur Facebook
                          • Partager sur Twitter
                            10 décembre 2024 à 17:33:42

                            Salut

                            Ni <tr>, ni <td> en-dehors de la boucle : une ligne est un enregistrement, donc un "tour de boucle" est une ligne. Il faut donc et la commencer, et la terminer dans la boucle. Comme les <td> sont des cellules dans la ligne, je pense que leur placement est ainsi logique : tout dans la ligne, donc à l'intérieur de la boucle  ;)

                            julp avait parlé de ne modifier que deux lignes, pas d'en déplacer d'autres  :D

                            • Partager sur Facebook
                            • Partager sur Twitter
                              10 décembre 2024 à 18:23:15

                              if ($row = $stmt->fetch()) {
                                              do {
                                                  echo "<thead>".
                                                  "" . _("<td>ID</td>") . "".
                                                  "" . _("<td>Nom et Adresse</td>") . "".
                                                  "" . _("<td>Email</td>") . "".
                                                  "" . _("<td>Total</td>") . "".
                                                  "" . _("<td>Date</td>") . "".
                                                  "</thead>".
                                                  "<tbody>".
                                                  "<tr>".
                                                     "<td>" . $row["id"]. "</td>".
                                                     "<td>" . $row["payer_name"]. "</td>".
                                                     "<td>" . $row["payer_email"]. " </td>".
                                                     "<td>" . $row["paid_amount"]. " </td>".
                                                     "<td>" . $row["created"]. "</td>".
                                                     "</tr>";
                                              }while($row = $stmt->fetch());
                                              "</tbody>";
                              comme ceci ? arf j'ai les lignes id, nom et adresse, email, total, date qui se repète pour chaque commande au lieu d'être une seule fois en haut du tableau
                              • Partager sur Facebook
                              • Partager sur Twitter
                                10 décembre 2024 à 18:40:36

                                Presque : toute ta partie thead + la balise ouvrante du tbody doivent se trouver entre le if et le do, pas dans le do (il te faudra donc ajouter un echo - ou, mieux, préférer la syntaxe alternative)

                                -
                                Edité par julp 10 décembre 2024 à 18:43:21

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  10 décembre 2024 à 18:48:56

                                  julp a écrit:

                                  Presque : toute ta partie thead + la balise ouvrante du tbody doivent se trouver entre le if et le do, pas dans le do (il te faudra donc ajouter un echo - ou, mieux, préférer la syntaxe alternative)

                                  -
                                  Edité par julp il y a 4 minutes


                                  je venais de trouver à L'instant :) merci pour votre patience.

                                  je vous souhaite une bonne soirée à vous 2 :)

                                  -
                                  Edité par lutinjoyeux 10 décembre 2024 à 18:49:30

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    10 décembre 2024 à 18:51:26

                                    Idéalement, ça donnerait ça :

                                    <?php if ($row = $stmt->fetch()): ?>
                                        <thead>
                                            <tr>
                                                <th><?= _('ID') ?></th>
                                                <th><?= _('Nom et Adresse') ?></th>
                                                <th><?= _('Email') ?></th>
                                                <th><?= _('Total') ?></th>
                                                <th><?= _('Date') ?></th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                        <?php do { ?>
                                            <tr>
                                                <td><?= htmlspecialchars($row['id']) ?></td>
                                                <td><?= htmlspecialchars($row['payer_name']) ?></td>
                                                <td><?= htmlspecialchars($row['payer_email']) ?></td>
                                                <td><?= htmlspecialchars($row['paid_amount']) ?></td>
                                                <td><?= htmlspecialchars($row['created']) ?></td>
                                            </tr>
                                        <?php } while($row = $stmt->fetch()); ?>
                                        </tbody>
                                    <?php endif ?>

                                    (et encore, il devrait y avoir des htmlspecialchars en sortie des appels à la fonction _)

                                    PS : potentiellement le htmlspecialchars qui pourrait ne pas aimer recevoir un entier suivant comment PDO renvoie les valeurs

                                    -
                                    Edité par julp 10 décembre 2024 à 18:57:17

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      10 décembre 2024 à 19:02:51

                                      <table>
                                                      <thead>
                                                          <th>ID</th>
                                                          <th><?php echo _("Nom et Adresse"); ?></th>
                                                          <th>Email</th>
                                                          <th><?php echo _("Total"); ?></th>
                                                          <th><?php echo _("Date"); ?></th>
                                                          </thead>.
                                                          <tbody>";
                                                  	<?php
                                                  if ($row = $stmt->fetch()) {
                                                      do {
                                                          echo"<tr>".
                                                             "<td>" . $row["id"]. "</td>".
                                                             "<td>" . $row["payer_name"]. "</td>".
                                                             "<td>" . $row["payer_email"]. " </td>".
                                                             "<td>" . $row["paid_amount"]. " </td>".
                                                             "<td>" . $row["created"]. "</td>".
                                                             "</tr>";
                                                      }while($row = $stmt->fetch());
                                                      "</tbody>";
                                                  } else {
                                                    echo "0 results";
                                                  }
                                                  $bdd->close();
                                      la fonction _ c'est pour mon traducteur gettext :) merci ;)
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      sécurité injection sql et query

                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                      • Editeur
                                      • Markdown