IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Requete PDO sécurisée ?


Sujet :

PHP & Base de données

  1. #1
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Février 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 257
    Par défaut Requete PDO sécurisée ?
    Bonjour,

    Généralement, je fais cela pour insérer dans une Bd
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      $req = $bdd->prepare('INSERT INTO table SET nom=:nom');
      $req->execute(array('nom' => $_POST['nom']));
    Aussi, je me suis amusé à envoyer cela dans un champ du formulaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <script type="text/javascript">alert('Boum');</script>
    Et bien cela fait bien Boum.
    Sauf si on fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strip_tags($_POST['nom'])
    Je pensais qu'une requête de cette sorte filtrait le code avant de l'envoyer dans la Bd.
    A moins que ce ne soit pas du tout ce type de requête qui s'appelle 'PDO'.

    Merci pour vos éclairages.

  2. #2
    Membre éprouvé Avatar de jisig
    Homme Profil pro
    null
    Inscrit en
    Avril 2014
    Messages
    146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Indonésie

    Informations professionnelles :
    Activité : null

    Informations forums :
    Inscription : Avril 2014
    Messages : 146
    Par défaut
    Tu te dois de sécuriser tes chaînes de caractères venant des utilisateurs manuellement (sauf avec un framework/librairies qui gère ça pour toi).

    un peu d'aide ici : https://secure.php.net/manual/fr/pdo.prepare.php

  3. #3
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Février 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 257
    Par défaut
    Merci jisig,
    Les docs du zéro, sont toujours aussi bien.

    Et est-ce que des strip_tags(); sur les POST
    peuvent faire l'affaire ?
    Ca fonctionne pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <script type="text/javascript">alert('Boum');</script>

  4. #4
    Membre éprouvé Avatar de jisig
    Homme Profil pro
    null
    Inscrit en
    Avril 2014
    Messages
    146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Indonésie

    Informations professionnelles :
    Activité : null

    Informations forums :
    Inscription : Avril 2014
    Messages : 146
    Par défaut
    https://secure.php.net/manual/fr/fun...strip-tags.php

    c'est une fonction qui a pour but de supprimer certains tags, mais pas de sécuriser une chaîne, je pense qu'il sera mieux de lire un tutoriel et/ou doc à ce sujet.

    edit : voir aussi

  5. #5
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 59
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Bonjour FeelWatt...

    Je me demande si ton problème ne vient pas plutôt du fait que tu ne fais pas tes requêtes préparées de la bonne façon... Voir manuel :
    http://php.net/manual/fr/pdo.prepare.php

    Tu fais un mix entre les requêtes préparées avec marqueurs anonymes et avec marqueurs nommés :

    1) marqueurs anonymes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     $req = $bdd->prepare('INSERT INTO table SET nom=?');
      $req->execute(array($_POST['nom']));
    OU
    2) marqueurs nommés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     $req = $bdd->prepare('INSERT INTO table SET nom=:nom');
      $req->execute(array(':nom'=>$_POST['nom']));
    Ca, c'est pour l'insertion en base. Si tu veux bien vérifier que ton expérience de code nuisible tombe à l'eau avec les bonnes syntaxes de requête préparée, je n'ai pas le temps là.
    Question aux cracks : faut-il s'interdire de placer directement des $_POST comme il fait, et passer par des variables intermédiaires du genre $toto=$_POST['toto'];, ou bien ça n'est plus un problème avec les requêtes préparées ?

    Par ailleurs, quand ensuite, tu réutiliseras tout ce que tu prends de ta base pour des affichages, tu seras bon pour appliquer la fonction htmlspecialchars pour éviter des déconvenues avec des apostrophes ou autres caractères enquiquinants qui feraient bugger ton HTML.
    http://php.net/manual/fr/function.htmlspecialchars.php

    3) récupération des données en lecture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $data=array();
    while ($row = $sth->fetch(PDO::FETCH_ASSOC)){
       $data[]=$row;
    }
    $keys=array_keys($data[0]);
    $i=0;
    do{
       foreach($keys as $key){
          $data[$i][$key]=htmlspecialchars($data[$i][$key]);
       }
       $i++;
    }while($i<count($data));
    En général, c'est là que je me prends une volée de bois vert par des cracks (coucou Jreaux, coucou rawSrc), et ça me vexe un peu... mais ça me remets les idées en place sur les bonnes pratiques, ce qui est le but recherché après tout ! Pas taper, pas taper !
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  6. #6
    Invité
    Invité(e)
    Par défaut
    Hello Dendrite,
    On parle de moi ?

    Pour reprendre le 1er post : on a 2 choses indépendantes.

    1- Une requête préparée a pour vocation de sécuriser la requête SQL et de la protéger des "injections SQL" *.
    POINT.

    * On peut aussi utiliser bindValue ou bindParam, qui prennent un paramètre définissant s'il s'agit d'un entier (PDO::PARAM_INT), une chaîne (PDO::PARAM_STR),...
    Ce qui augmente un peu le niveau de sécurité.

    2- le fait qu'il y ait un <script> dans le champ n'a RIEN A VOIR avec une quelconque "injection SQL" !
    La preuve : rien n'empêche d'enregistrer du code HTML (donc des balises HTML) dans une table de bdd (via un textarea généralement)

    DONC, il faut sécuriser aussi les champs de formulaire, CONTRE les "codes HTML malveillants" :

    Au minimum.

    ** Il existe aussi des fonctions PHP de validation d'email, d'URL,... : voir filter_validate(),... Filtres de validation
    Dernière modification par Invité ; 21/12/2018 à 11h08.

  7. #7
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Je complète en précisant que la protection XSS se fait en général à l'affichage et non à l'insertion. La base doit autant que faire se peux contenir des données brutes non transformées.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    la règle est simple :
    tu sécurises tes enregistrements en base de données avec PDO et le mécanisme de préparation
    tu sécurises tes données à l'affichage avec htmlspecialchars(), dès que tu affiches n'importe quoi sur une page web en provenance de l'utilisateur : c'est htmlspecialchars($value, ENT_QUOTES, 'utf-8');Et fais attention, il y a pléthore de fonctions texte en PHP qui ne sont pas compatibles avec unicode

  9. #9
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Pas mieux : jreaux, grunt et rawsrc ont tout dit
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  10. #10
    Invité
    Invité(e)
    Par défaut
    Merci Celira pour ton analyse, intelligente et subtile.



    J'insiste quand même sur le fait qu'on n'est pas obligé d'enregistrer tout et n'importe quoi en BDD.

    On est en droit d'effectuer une "gestion d'erreur" (c'est même recommandé !) :
    • validation des emails, URL,... (comme je l'ai dit) : Filtres de validation
    • suppression de code manifestement "malveillant",... (pas de balises HTML dans les champs "text",...)
    • ...

  11. #11
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Citation Envoyé par jreaux62 Voir le message
    Merci Celira pour ton analyse, intelligente et subtile.



    J'insiste quand même sur le fait qu'on n'est pas obligé d'enregistrer tout et n'importe quoi en BDD.

    On est en droit d'effectuer une "gestion d'erreur" (c'est même recommandé !) :
    • suppression de code manifestement "malveillant",... (pas de balises HTML dans les champs "text",...)
    C'est au client (navigateur, applicatif, cli, etc ...) qui utilise les données de définir ce qui est malveillant pour lui , pas au serveur qui ne connait potentiellement pas l'étendue et le type de client qui vont utiliser les données qu'il met à disposition.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Février 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 257
    Par défaut
    Ok,
    merci à tous pour ces éclaircissements !
    Je pense que ça servira à d'autres.

    grunk
    C'est au client (navigateur, applicatif, cli, etc ...) qui utilise les données de définir ce qui est malveillant pour lui , pas au serveur qui ne connait potentiellement pas l'étendue et le type de client qui vont utiliser les données qu'il met à disposition.
    jreaux62
    J'insiste quand même sur le fait qu'on n'est pas obligé d'enregistrer tout et n'importe quoi en BDD.

    On est en droit d'effectuer une "gestion d'erreur" (c'est même recommandé !) :

    validation des emails, URL,... (comme je l'ai dit) : Filtres de validation
    suppression de code manifestement "malveillant",... (pas de balises HTML dans les champs "text",...)
    ...
    rawsrc
    la règle est simple :
    tu sécurises tes enregistrements en base de données avec PDO et le mécanisme de préparation
    tu sécurises tes données à l'affichage avec htmlspecialchars(), dès que tu affiches n'importe quoi sur une page web en provenance de l'utilisateur : c'est htmlspecialchars($value, ENT_QUOTES, 'utf-8');
    > Pour les données à l'affichage, quel en est le danger ?

    ---
    Pour être sûr que mes requêtes soient bien en PDO,
    j'ai demandé à mon ami Qwant "mysql php pdo".
    et suis arrivé sur:
    https://www.developpez.net/forums/bl...pdo-soupe-lit/
    Donc Pdo, une soupe et au lit

    Big Up à
    - Andry.ayme
    - Celira
    - Dendrite
    - Jreaux62
    - MaitrePylos
    - ProgElect
    - Rawsrc
    - Willy_k
    - LaurentSc
    (Et sans oublier ceux qui ne sont pas dans la liste)

  13. #13
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Pour les données à l'affichage, quel en est le danger ?
    Ce qu'on appelle les faille XSS , qui sont l’exécution de script sur le navigateur client. Ca peut aller du simple "alert()" qui s'affiche au vol d'information voir à la prise de contrôle.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Février 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 257
    Par défaut
    Même pas une sieste plus tard...
    J'ai repris Blogs > Dendrite > PDO une soupe et au lit ! (https://www.developpez.net/forums/bl...pdo-soupe-lit/)
    > 7 - Requête INSERT

    Avec:
    1- Tester le GET['id'] == entier
    2- Boucler les POST
    3- strip_tags sur les POST

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    <?php 
    // 1- Tester le GET['id'] == entier
    if (!filter_var($_GET['id'], FILTER_VALIDATE_INT)) {
      echo 'Erreur id';
      // Pas toucher barre d'adresse 
        // > session_unset();
        // > insert into black_list 
        // > header('Location: https://fr.wikipedia.org/wiki/Babar');
    }
    else { 
     
    $table=strip_tags($_POST['table']);
     
        // 2- Boucler les POST
       foreach ($_POST as $key => $value) {
     
            try { 
               $sql="UPDATE $table SET $key = ? WHERE id = ?;";
               $stmt = $bdd->prepare($sql);
     
               // Inutile car vérifié avec FILTER_VALIDATE_INT
               $id=strip_tags($_GET['id']); 
     
               // 3- strip_tags sur les POST
               $stmt->execute(array(strip_tags($value),$id));
     
               $nb_update = $stmt->rowCount();
               echo $nb_update.' modif effectuée: '.$key.' > '.$value.'<br/>';
            } 
            catch (Exception $e) {
               print "Erreur ! " . $e->getMessage() . "<br/>";
            }
     
          } // foreach
     
    } // else (!filter_var($_GET['id'], FILTER_VALIDATE_INT))
    ?>
    Qu'en pensez-vous ?

    ---
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $table=strip_tags($_POST['table']);
    bien pratique, mais ça donne le nom de la table à qui veut le connaitre, non ?

    ---
    J'aime bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!filter_var($_GET['id'], FILTER_VALIDATE_INT))
    Merci Celira.
    Comme on bosse qu'avec des id de table en GET, je pense qu'on va se le mettre à toutes les pages.

    ---

    J'aurais bien aimé faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (strip_tags($value)==true) {echo "Cramé !";}
    La solution est peut-être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (strstr($value, '</')) {echo "Cramé !";}

  15. #15
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    mais pourquoi diable tu veux coller des strip_tags() partout ?
    C'est inutile et en plus casse les chaînes unicode.

    Le mécanisme de préparation des requêtes SQL te protège des injections SQL
    et le mécanisme d'échappement des données à l'affichage te protège des failles XSS
    htmlspecialchars() effectue ces remplacements :
    Caractère Remplacement
    & (ET commercial) &amp;
    " (double guillemet) &quot; sauf si ENT_NOQUOTES
    ' (simple guillemet) ' (pour ENT_HTML401) ou &apos; (pour ENT_XML1, ENT_XHTML ou ENT_HTML5), mais seulement lorsque ENT_QUOTES est défini
    < (inférieur à) &lt;
    > (supérieur à) &gt;
    Ainsi tous les caractères qui pourraient être interprétés par le navigateur sont rendus inoffensifs.
    Après je ne vois pas ce que tu ne comprends pas

  16. #16
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Février 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 257
    Par défaut
    Ok, tu as raison.

    L'idée de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (strip_tags($value)==true) {echo "Cramé !";}// ou
    if (strstr($value, '</')) {echo "Cramé !";}
    Etait de repérer quelque testeur de code qui viendrait chercher des failles.

    ---
    Autre chose:
    Je me demandais comme j'affiche les pages avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <a href="index.php?p=page.php">La page</a>
    avec dans l'index.php
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!@include($_GET['p'])) {include('home.php');}
    On pourrait passer du code par ce $_GET['p'].
    Faudrait-il le sécuriser ?

    Une idée:
    Lister tous les noms des pages.php dans le dossier,
    et si le GET['p'], n'en fait pas partie > c'est une tentative.

  17. #17
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!@include($_GET['p'])) {include('home.php');}
    Ça, ça me plaît moyen, parce qu’on include un chemin qui vient du client. Certaines configurations autorisent l’inclusion de fichiers se trouvant sur des serveurs distants, et là tu perds totalement le contrôle, voir le commentaire de John Carthy sur la doc de include.

    Et le @, pas mauvais en soi, mais souvent révélateur d’une méconnaissance du langage. En l’occurence on pourrait utiliser une fonction de vérification comme file_exists ou realpath ou encore un objet SplFileInfo pour savoir si le fichier existe sans, du même coup, exécuter son contenu en n’ayant pas la connaissance préalable de ce qu’il contient, ce qui est, admettons-le, très imprudent.

    Malheureusement il n’existe pas de fonction native « can_be_included » (je viens d’inventer le nom) qui permettrait de savoir si le chemin passé existe sous au moins un des chemins spécifiés dans le include path. Il faut coder cette fonction soi-même.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  18. #18
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Février 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 257
    Par défaut
    Ok, merci Watilin,
    J'ai fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    index.php?p=http://php.net/manual/fr/function.include.php
    Cela renvoi sur home.php
    Aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $info = new SplFileInfo($_GET['p']);
    var_dump($info->getRealPath());
    Renvoi "boolean false" pour l'adresse ci-dessus et "string "C:\wamp\www\...etc.php (length=50)"
    dans le cas où le GET['p'] est bon.
    Ca évite l'idée de lister les noms des pages.php dans le dossier.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [PDO] Les requete PDO ne prennent pas en compte la premier ligne de résultat
    Par -Fly- dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 28/03/2012, 21h59
  2. [PDO] resultat requete PDO sous forme de tableau
    Par kate59 dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 11/08/2011, 18h57
  3. [MySQL] Requete PDO et LIMIT de SQL
    Par heretik25 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 30/06/2011, 11h25
  4. [PDO] requete PDO et bindParam
    Par totofe49 dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 18/11/2010, 18h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo