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

Langage PHP Discussion :

[Sécurité] Comment sécuriser un champ textarea ?


Sujet :

Langage PHP

  1. #1
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut [Sécurité] Comment sécuriser un champ textarea ?
    Bonjour,

    Je dois sécuriser un formulaire.
    Pour certains champs je sais le type de données attendues, donc c'est très bien j'utilise les expregs.
    Mais pour le textarea, je ne sais pas ce que l'on peut m'envoyer et je ne peux pas interdire de caractères.

    Donc comment le filtrer au mieux ?
    Je peux faire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    htmlentities(mysql_real_escape_string($textarea))
    Mais est-ce suffisant et sinon que faire d'autre ?

    Merci de votre aide

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 79
    Points : 72
    Points
    72
    Par défaut
    Salut,

    tu veux le sécuriser contre quoi (certains mots,...) ?

  3. #3
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Non contre les attaques xss, injections sql et autres joyeusetés. Les mots doivent rester libres et je ne peux pas bloquer les caractères spéciaux.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    alors...

    si tu veux faire un bon filtrage :

    1)
    * Verifier en php le reglage des magicquotes (avec get_magic_quotes_gpc())
    * Si activé alors stripslashes sur la variable

    => Tu obtiens dorenavant un champ qui correspond exactement a ce que l'utilisateur a tapé !!

    Ensuite, le traitement a faire depend de l'utilisation :

    2)
    * pour inserer dans une base de données :
    mysql_real_escape_string
    * pour afficher sous forme de texte :
    htmlentities
    * pour afficher dans un value de formulaire ou un autre attribut d'une balise html :
    addslashes

    Ensuite, ton traitement est sécurisé... a condition que :
    * dans toutes les requetes qui travaillent sur le champs utilisé pour stocker l'info tu utilise des quotes autour du champs : SELECT ... champ = '$champ', etc...
    * chaque fois que tu récupere l'info depuis la base, tu dois refaire le traitement en fonction de l'utilisation a partir du point 2

    Dans la pratique, je te conseille de tester TOUT tes champs avec le crash test suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a'a"a/a\a<b>a</b>a<br>a
    si cette chaine se réaffiche exactement telle qu'elle a été tapée partout sans faire aucune erreur, il y a de grande chance que ton code soit a peu pres correct ;o)
    (et quand je dis exactement, c'est exactement ! pas de \ en trop, pas de \ en moins, pas de "a" en gras ou de retour chariot interprété avec <br>, et les tests sont a faire en affichage, creation, modification et suppression de ton objet)

    Je crois que j'ai fait le tour, j'ai oublié qqchose ? ;o))

  5. #5
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    salut Fladnag, merci pour cette réponse complète.

    Alors une question déjà :

    Ensuite, ton traitement est sécurisé... a condition que :
    * dans toutes les requetes qui travaillent sur le champs utilisé pour stocker l'info tu utilise des quotes autour du champs : SELECT ... champ = '$champ', etc...
    Je fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT...champ='.$champ.'
    ça revient au même, qu'est ce que t'en pense ? Et au fait, pourquoi les quotes sont un support contre les injections sql ?

    Sur un autre post, j'ai lu cette phrase :
    D'ailleurs, faire un "mysql_real_escape_string" sur une variable placé directement dans une requête sans apostrophe n'empêche pas le "piratage".
    ça semble confirmer. Mais alors pourquoi mysql_real_escape_string() + apostrophes dans la requête = sécurité et pourquoi sans les apostrophes ça ne l'est plus ?

  6. #6
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    Citation Envoyé par JackBeauregard
    Je fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT...champ='.$champ.'
    ça revient au même, qu'est ce que t'en pense ? Et au fait, pourquoi les quotes sont un support contre les injections sql ?
    C'est justement ce qu'il faut eviter ;o)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ... champ=\''.$champ.'\'....
    ou 
    SELECT ... champ='".$champ."'...
    est correct.

    ta requete va construire :
    donc imaginons une requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM membres WHERE login=$login AND password=$password
    maintenant, je rentre comme login : $login="admin--"

    la requete devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM membres WHERE login=admin-- AND password=
    manque de bol pour toi, -- veux dire que le reste de la ligne de la requete SQL est un commentaire... donc on ne fait aucune verification sur le mot de passe !

    Si tu met des quotes, tu obtient comme requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM membres WHERE login='admin--' AND password=''
    et là mysql va bien comprendre que c'est la chaine "admin--" qu'il faut verifier.

    Ce n'est qu'un exemple de ce qui est possible. Si le sujet t'interesse, je te conseille de lire les articles sur l'injection sql disponible sur ce site : http://www.phpsecure.info/v2/zone/pArticle
    ce n'est pas un panel exhaustif de ce qui est possible, mais c'est une tres bonne introduction, et ca permet en principe de se rendre compte de la fragilité d'un script php mal codé ;o)

  7. #7
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Je vais voir ton lien, merci pour tes explications.

    J'ai revérifié mon code, mes requêtes sont comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $requete="SELECT descriptionFROM complements WHERE id = '".$id."' ";
    Peux-tu me confirmer que cela c'est bon, s'il te plait ?

    Aussi j'en ai une comme ça, et là je n'arrive pas à la placer entre '".."' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "SELECT libelle    FROM definitions WHERE mot like '$lettre%' ";
    Celle là j'ai essayé ça '".$lettre.%"' ou '".$lettre"'% mais ça fait foirer ma requête.
    En plus $lettre peut contenir des lettres ou le signe - donc au vu de ton exemple même une expreg, qui n'autorise que des lettres et le trait d'union, ne servirait à rien.

  8. #8
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    @Fladnag : addslashes() n'est jamais utile car si tu envoies tes données dans une page HTML, alors il est préférable d'utiliser htmlentities() avec son deuxième paramètre ENT_QUOTES.

    [Edit] Au passage :
    http://securite.developpez.com/faq/?..._sql_injection

  9. #9
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Bon dans le même genre parce que je ne vais pas ouvrir un sujet que pour ça, j'ai le problème ci-dessous :

    Requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FROM commentaire 
    WHERE idDef='".$idDef."' 
    ORDER BY timeDernierSousCom  DESC 
    LIMIT ".$debut.",".$fin."";
    Donc ici ça fonctionne bien.

    Par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FROM commentaire 
    WHERE idDef='".$idDef."' 
    ORDER BY timeDernierSousCom  DESC 
    LIMIT '".$debut."','".$fin."'  ";
    Là j'ai une erreur déclenché par les simples quotes. Mais ailleurs ça fonctionne bien, comme dans la clause WHERE avec $idDef.

    Donc pourquoi ça rate pour les deux autres (à tout hasard je précise que $debut et $fin sont des chiffres entier).

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    625
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 625
    Points : 822
    Points
    822
    Par défaut
    hello,

    lorsque tu utilises des entiers dans tes requetes, les apostrophes sont inutiles (voir meme déconseillées, si quelqu'un peut confirmer ?)

    dans la clause LIMIT en l'occurence, elles font meme planter la requete.
    Pourfendeur de singletons en croisade

  11. #11
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Oui mais pourtant j'ai une autre requête où j'utilise un entier et ça ne foire pas en le placant comme suit :'".$entier."'

    Dans mon exemple au dessus, ça ne viendrait pas de la clause LIMIT ?

  12. #12
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Petibidon vient de te dire que c'est le cas, en effet.
    @Petibidon : Tout dépend... Si tu sais que tu protègeras toujours tes valeurs entières, alors il est préférable de ne pas mettre de quotes puisque cela permet au SGBD de traiter correctement le type de la donnée. Sinon, peut-être que les quotes sont un moindre mal (mais pas une solution).

  13. #13
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Petibidon vient de te dire que c'est le cas, en effet.
    Oui mais j'ai pas assez dormi aujourd'hui alors hein...



    Bon dans la série des questions crétines, puisque ça semble être le jour, en voilà encore une :

    A réception des données de l'url je fais ça pour tester le masque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if(preg_match('/^[a-z]+$/',$_GET['definition']))//accepte lettres et trait d'union
    {$definition=mysql_real_escape_string(htmlentities($_GET['definition']));}
    Mais en plus à divers endroit des scripts qui sont inclus dans la page initiale, j'ai des requêtes et je refais avant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $definition=mysql_real_escape_string(htmlentities($definition))
    ça sert à rien vous allez me dire, pas vrai ? J'avais dû faire ça parce que les requêtes étaient placées dans des fichiers requis.

  14. #14
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Peut-être suis-je également fatigué mais il me semble t'avoir déjà dit (et je ne suis pas le seul) que ces deux fonctions n'ont pas la même utilité. Il ne faut pas les utiliser conjointement car c'est une erreur de logique.

  15. #15
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Bah la question portait pas sur ça, mais bon c'était une fausse question de toute façon. Je voulais savoir si le pirate pouvait modifier une variable en cours de scripts.
    On va marquer résolu...

    Merci à tous

  16. #16
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    En cours de script ? Bien sûr que non : chaque action de l'utilisateur déclenche une exécution de script mais l'utilisateur ne peut pas intervenir pendant ce procesus.

  17. #17
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Donc je filtre une fois à réception de la variable $_GET['var'], et c'est bon pour toutes les requêtes de la page y compris celles situées dans des fichiers requires.

  18. #18
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    S'il s'agit d'une valeur numérique, il suffit de filtrer une fois au départ pour pouvoir utiliser la variable dans les requêtes et pour l'envoyer dans le HTML.
    S'il s'agit d'une variable texte, il faut la filtrer pour chaque utilisation, avec la fonction qui va bien.
    • mysql_real_escape_string() pour une requête MySQL ;
    • htmlentities() avec ses 3 paramètres pour le HTML ;
    • preg_quote() pour une regex ;
    • etc.
    Je suis en train de finaliser un article qui résume tout cela.

  19. #19
    Inscrit
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    531
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 531
    Points : 282
    Points
    282
    Par défaut
    Ton article sera le bienvenue Yogui, merci d'avance pour celui-ci.

    S'il s'agit d'une valeur numérique, il suffit de filtrer une fois au départ pour pouvoir utiliser la variable dans les requêtes et pour l'envoyer dans le HTML.
    S'il s'agit d'une variable texte, il faut la filtrer pour chaque utilisation, avec la fonction qui va bien.
    Bon alors je suis de nouveau embrouillé. Parce que plus haut tu dis :
    En cours de script ? Bien sûr que non : chaque action de l'utilisateur déclenche une exécution de script mais l'utilisateur ne peut pas intervenir pendant ce procesus.

    Dans mon cas je reçois deux types de variables par l'URL, une numérique et une texte + tiret ou texte seul (exemple : "mot-nouveau" ou "mot" avec que des lettres dans les deux cas).
    J'ai donc ces deux preg_match pour vérifier le masque :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    //on vérifie si on a un chiffre
    if(preg_match('/^[0-9]/',$_GET['chiffre']))
    {$chiffre=intval($_GET['chiffre']);} 
     
    //on vérifie si on des lettres
    if(preg_match('/^[a-z]+$/',$_GET['definition']))
    {$definition=mysql_real_escape_string($_GET['definition']);}
    Dans les deux cas, les variables sont utilisées pour plusieurs requêtes à l'intérieur de la page.
    Donc si je suis ce que tu dis dans ta dernière réponse, le gars pourrait trafiquer en cours de page $definition mais ne pourrait le faire avec $chiffre ?


    **edit** le coup du intval($chiffre) après avoir vérifié par expreg que l'on a des chiffres est un peu inutile... mais là je suis pas encore sur ça, c'est pas comme ça dans mon script. Et si on a qu'une lettre, est-ce tout de même du texte et qu'est-ce que ça change par rapport à la question qui nous préoccupe à savoir la modification des données en cours de page selon que la variable est numérique ou que sa valeur est un texte ?

  20. #20
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Il faut bien voir que l'utilisateur fait simplement une demande de page Web identifée par une URI et contenant éventuellement des données en GET, POST et/ou COOKIE. Au-delà, l'utilisateur ne peut pas faire grand chose à part attendre la réponse du serveur.
    Durant toute l'exécution du script, ton internaute n'a absolument aucun contrôle sur ce qu'il se passe. Du coup, à mon sens, il ne peut pas agir "au milieu" de l'exécution. De mon point de vue, toutes les variables soumises par l'utilisateur doivent être filtrées une première fois au départ du script puis, selon le cas, lors de leur utilisation.

    Chris Shiflett recommande l'utilisation de tableaux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $mysql = array();
    $mysql['username'] = mysql_real_escape_string($_POST['username']);
    $mysql['password'] = md5($_POST['password']);
     
    $html = array();
    $html['username'] = htmlentities($_POST['username'], ENT_QUOTES, 'ISO-8859-1');
     
    unset($_POST);

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 3
    Dernier message: 23/08/2014, 17h08
  2. Réponses: 2
    Dernier message: 18/05/2010, 20h03
  3. Comment renommer un champ avec Module BD?
    Par technico dans le forum Bases de données
    Réponses: 4
    Dernier message: 27/01/2004, 21h24
  4. [CR] Comment trouver un champs dans un report ??
    Par Madduck dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 18/09/2003, 08h31
  5. [langage] Comment rajouter des champs dans une liste
    Par toto_titi dans le forum Langage
    Réponses: 4
    Dernier message: 28/08/2003, 14h09

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