Discussion:
Encore un probleme d'apostrophe
(trop ancien pour répondre)
Pascale
2007-06-10 18:38:36 UTC
Permalink
Bonjour à tous,

Après plusieurs mois d'interruption, je reviens sur la programmation de mon
site d'identification de plantes. J'ai encore une histoire d'apostrophe qui
me pose souci, et je ne refuserais pas un peu d'aide.

Lorsqu'une personne passe une demande d'identification, ou une proposition
d'identification, les données saisies sont passées par un formulaire.
J'effectue quelques contrôles pour virer les données qui pourraient être
dangereuses et éviter les problèmes de ' et de " :

$douteux=trim($douteux);
$douteux=strip_tags($douteux);
$propre=trim(htmlspecialchars($douteux,ENT_COMPAT,'ISO8859-15'));

J'étais venue il y a quelque mois sur ce forum pour avoir des lumières sur
la gestion des ' et des ", et il en était ressorti que htmlspecialchars
était une bonne solution, et en effet, lorsque j'insère mes données après
les avoir contrôlées :

$ins="INSERT INTO matable VALUES ('','$ch2,'','$ch4')";
mysql_query($ins) or die('Erreur SQL !'.$ins.'<br>'.mysql_error());

L'insertion ne pose jamais de problème et les données sont bien comme elles
doivent être (magic_quotes_gpc est « on »). Par exemple, j'ai dans ma base
de données un descriptif de ce genre :
C'est ma &quot;belle&quot; plante.

Les ennuis commencent lorsque je veux faire un UPDATE sur des données déjà
entrées, ce qui arrive lorsqu'un utilisateur met à jour sa demande. Lui,
écrit dans une table temporaire (après contrôle des données), je fais donc
un INSERT, ça marche. Mais lorsque je valide sa demande de modification, je
dois remplacer les anciennes données par les nouvelles dans la table
principale, et là, ça va plus du tout, dès lors que le texte contient une
apostrophe : je me prends un message d'erreur de ce genre :

Erreur SQL !UPDATE matable SET hauteur='nouvelle hauteur',envir='C'est ma
belle plante' WHERE numfiche='1528'
You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'est ma belle
plante'

Donc manifestement, c'est bien l'apostrophe qui coince. J'aimerais
comprendre pourquoi et surtout, comment résoudre ce casse-tête...
--
Pascale
Gromitt
2007-06-11 05:58:28 UTC
Permalink
Post by Pascale
Bonjour à tous,
Aloha,
Post by Pascale
[...]
$ins="INSERT INTO matable VALUES ('','$ch2,'','$ch4')";
mysql_query($ins) or die('Erreur SQL !'.$ins.'<br>'.mysql_error());
[...]
L'insertion ne pose jamais de problème et les données sont bien comme
elles doivent être (magic_quotes_gpc est « on »).
Ca, c est mal, mais si tu m as pas du tout le controle sur le serveur
et sur cette option, c est pardonnable.
Post by Pascale
[...]
Erreur SQL !UPDATE matable SET hauteur='nouvelle hauteur',envir='C'est ma
belle plante' WHERE numfiche='1528'
[...]
Donc manifestement, c'est bien l'apostrophe qui coince. J'aimerais
comprendre pourquoi et surtout, comment résoudre ce casse-tête...
La manière recommandée pour "échapper" les données insérées dans une
base de données MySQL est de passer par la fonction
"mysql_real_escape_string()" appliquée sur des données brutes, c est à
dire sur des données non "échappées" préalablement entre la saisie par
l'utilisateur et l'insertion/la mise a jour dans la bd :

$field = isset($_POST['field']) ? (string) $_POST['field'] : ''; //
donnée externe
$sqlField = mysql_real_escape_string($field);
$query = 'INSERT INTO `table` (`field`) VALUES ('.$sqlField.')';
mysql_query($query, $db) or die('raté');

mysql_real_escape_string() se charge d'adapter tous les caracteres
problematiques (dont les apostrophes) en données (relativement bien)
sécurisées, pretes a etre manipulées par MySQL, en vue de faire des
INSERT/UPDATE/DELETE/SELECT/...

Si tu echappes en HTML (htmlspecialchars(), htmlentitites(), ...) une
donnée entre le moment ou tu recuperes sa valeur dans un formulaire et
le moment ou tu l'inseres/la mets a jour dans la bd, tu pourrais avoir
la surprise d'avoir des données etranges dans ta bd. L'échappement
HTML est à réserver en vue de produire un affichage (contenu X/HTML)
aux visiteurs, que ce soit du texte provenant d'un formulaire ou d'une
base de données.

En espérant ne pas avoir été trop confus,

--
Gromitt
Pascale
2007-06-11 16:05:47 UTC
Permalink
Post by Gromitt
Ca, c est mal, mais si tu m as pas du tout le controle sur le serveur
et sur cette option, c est pardonnable.
Je pourrais toujours le mettre à off, mais pourquoi ? Cette option est bien
pratique. Non ? C'est un peu mal ou franchement MAL ?
Post by Gromitt
La manière recommandée pour "échapper" les données insérées dans une
base de données MySQL est de passer par la fonction
"mysql_real_escape_string()" appliquée sur des données brutes, c est à
dire sur des données non "échappées" préalablement entre la saisie par
$field = isset($_POST['field']) ? (string) $_POST['field'] : ''; //
donnée externe
$sqlField = mysql_real_escape_string($field);
$query = 'INSERT INTO `table` (`field`) VALUES ('.$sqlField.')';
mysql_query($query, $db) or die('raté');
mysql_real_escape_string() se charge d'adapter tous les caracteres
problematiques (dont les apostrophes) en données (relativement bien)
sécurisées, pretes a etre manipulées par MySQL, en vue de faire des
INSERT/UPDATE/DELETE/SELECT/...
Si tu echappes en HTML (htmlspecialchars(), htmlentitites(), ...) une
donnée entre le moment ou tu recuperes sa valeur dans un formulaire et
le moment ou tu l'inseres/la mets a jour dans la bd, tu pourrais avoir
la surprise d'avoir des données etranges dans ta bd.
Quel genre ?
Post by Gromitt
 L'échappement
HTML est à réserver en vue de produire un affichage (contenu X/HTML)
aux visiteurs, que ce soit du texte provenant d'un formulaire ou d'une
base de données.
Je ne suis pas sûre de comprendre, mais je dirais que c'est bien le cas :
lorsqu'une personne entre une demande (ou une modification de demande),
elle peut la visualiser, et, éventuellement, la corriger : l'utilisateur
revient alors au formulaire, dans lequel vont bien sûr figurer les données
qu'il vient d'entrer (afin qu'il n'ait pas à tout ressaisir).
Post by Gromitt
En espérant ne pas avoir été trop confus,
Compte tenu de mon niveau en php, les explications sont vite confuses pour
moi, mais là ça va à peu près (-:
--
Pascale
Patrick Mevzek
2007-06-12 07:02:36 UTC
Permalink
Post by Pascale
Post by Gromitt
Ca, c est mal, mais si tu m as pas du tout le controle sur le serveur
et sur cette option, c est pardonnable.
Je pourrais toujours le mettre à off, mais pourquoi ? Cette option est bien
pratique. Non ? C'est un peu mal ou franchement MAL ?
magic_quotes_gpc c'est mal (d'ailleurs ca va disparaître dans PHP 6)
parce qu'en général on l'utilise en croyant que cela suffit pour se
prémunir de toutes les injections SQL (notamment) car on reste dans le
rêve malheureusement plus que partagé que les injections SQL sont dûes aux
guillements/apostrophes et uniquement à cela.

Accessoirement c'est aussi un peu la plaie quand on oublie son existence
(ce qui est quelque part son but, cela ne s'appelle pas *magic* pour
rien), par exemple si son serveur de développement (chez soi) et de
production (chez l'hébergeur) ne sont pas configurés pareil, parce que ca
fait deux cas de figure différents, si on se met à faire du addslashes par
exemple (toujours quand on est dans la mythologie du paragraphe précédent
par rapport aux injections).

C'est bien que cela disparaisse dans PHP 6.
C'est mal qu'il faille attendre PHP 6 pour que cela disparaisse.
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>
Pascale
2007-06-12 10:55:41 UTC
Permalink
magic_quotes_gpc c'est mal [couic]
Merci pour cette explication claire.

Par contre, ce que je ne comprends toujours pas, c'est pourquoi je peux
faire un INSERT sans problème avec mes données (cf mon premier message),
mais pas un UPDATE...
--
Pascale
Pascale
2007-06-12 10:55:41 UTC
Permalink
Post by Pascale
Je ne suis pas sûre de comprendre, mais je dirais que c'est bien le
cas : lorsqu'une personne entre une demande (ou une modification de
l'utilisateur revient alors au formulaire, dans lequel vont bien sûr
figurer les données qu'il vient d'entrer (afin qu'il n'ait pas à tout
ressaisir).
Je me réponds à moi-même (:
Je viens de mettre magic_quotes_gpc à Off (j'ai vérifié dans la
configuration php que la modif était bien passée).
Je viens de remplacer htmlspecialchars par mysql_real_escape_string au
moment de la visualisation/vérification des données saisies par
l'utilisateur lorsqu'il fait une demande d'identification.

Je filtre mes données ainsi :

function filtre($douteux)
{
$douteux=trim($douteux);
$douteux=strip_tags($douteux);
$propre=mysql_real_escape_string($douteux);
return $propre;
}

Lorsque l'utilisateur veut visualiser les données qu'il a entrées, je fais
les vérification suivantes :

if (empty($_POST['nomplante']))
{echo 'Le titre de la demande est manquant !<br>';
$errtxt='1';}
else
{$nomplante=filtre($_POST['nomplante']);
if ($nomplante!='')
{$_SESSION['nomplante']=$nomplante;}
else
{echo 'Le titre de la demande est manquant !<br>';
$errtxt='1';}
}

Si l'utilisateur revient sur le formulaire avec le bouton "Corriger", le
contenu des champs du formulaire est tronqué après un " (mais pas après une
apostrophe ). Bizarre ou normal ?
--
Pascale
Gromitt
2007-06-13 07:27:55 UTC
Permalink
Post by Pascale
[...]
Je viens de mettre magic_quotes_gpc à Off (j'ai vérifié dans la
configuration php que la modif était bien passée).
Je viens de remplacer htmlspecialchars par mysql_real_escape_string au
moment de la visualisation/vérification des données saisies par
l'utilisateur lorsqu'il fait une demande d'identification.
Il ne faut pas forcément remplacer l'un par l'autre, mais plutôt
utiliser les deux, en choisissant le bon au bon moment (mais surtout
pas les deux en meme temps).
Post by Pascale
function filtre($douteux)
{
$douteux=trim($douteux);
$douteux=strip_tags($douteux);
$propre=mysql_real_escape_string($douteux);
return $propre;
}
Cette fonction *pourrait* servir à préparer des données en vue des les
insérer dans une base de données MySQL, et rien d'autre. Par contre,
pour "sécuriser" du contenu html, niet, htmlspecialchars/htmlentities
sont plus adaptés à ce cas.
Post by Pascale
Lorsque l'utilisateur veut visualiser les données qu'il a entrées, je fais
if (empty($_POST['nomplante']))
{echo 'Le titre de la demande est manquant !<br>';
$errtxt='1';}
else
{$nomplante=filtre($_POST['nomplante']);
if ($nomplante!='')
{$_SESSION['nomplante']=$nomplante;}
else
{echo 'Le titre de la demande est manquant !<br>';
$errtxt='1';}
}
Bingo, on se sert de la fonction de filtrage MySQL pour filtrer
(modifier) des chaînes de caractères, que l'on n'insere pas
immédiatement après dans une bd, mal ;)
Post by Pascale
Si l'utilisateur revient sur le formulaire avec le bouton "Corriger", le
contenu des champs du formulaire est tronqué après un " (mais pas après une
apostrophe ). Bizarre ou normal ?
A vue de nez, normal, mysql_real_escape_string() n'affecte pas (a
priori) les double-quotes, ca casse donc le contenu des tags html :
<input type="text" name="x" value="y"abc" />

Voici un schema que je juge typique pour l'echappement des données :

donnée saisie d'un formulaire, pour (ré-)affichage à l'écran
=> htmlentities/htmlspecialchars

donnée saisie d'un formulaire, pour enregistrement dans la bd
=> mysql_real_escape_string

donnée lue de la bd, pour affichage à l'écran (html, incluant les
<input />)
=> htmlentities/htmlspecialchars

donnée lue de la bd, pour mise à jour dans la bd
=> mysql_real_escape_string

analyse d'une donnée recue d'un formulaire (tests de validation)
=> aucun échappement

analyse d'une donnée lue dans la bd
=> aucun échappement

soit en résumé :
* affichage à l'écran (rendu html) : htmlentities/htmlspecialchars
* ecriture dans la bd : mysql_real_escape_string
* analyse de données : aucun échappement

L'utilisation conjointe de ces deux méthodes d'echappement conduit à
des "aberrations" dans la bd, tel que des chaines stockées sous la
forme "p&eacute;achep&éacute;", qui prennent bien plus de place, et
qui risquent de créer d'autres aberrations au moment de faire un rendu
à l'écran, si on refait un autre echappement html.

Je termine en te proposant un document de référence sur le sujet, par
Chris Shiflett :
http://conf.phpquebec.com/slides/2005/mastering-php-security.pdf
Pascale
2007-06-13 11:10:47 UTC
Permalink
[couic]
* affichage à l'écran (rendu html) : htmlentities/htmlspecialchars
* ecriture dans la bd : mysql_real_escape_string
* analyse de données : aucun échappement
L'utilisation conjointe de ces deux méthodes d'echappement conduit à
des "aberrations" dans la bd, tel que des chaines stockées sous la
forme "p&eacute;achep&éacute;", qui prennent bien plus de place, et
qui risquent de créer d'autres aberrations au moment de faire un rendu
à l'écran, si on refait un autre echappement html.
J'en suis arrivée à peu près à cette conclusion en cherchant de mon côté, à
savoir que j'avais besoin de htmlspecialchars ET mysql_real_escape_string,
mais effectivement, à lire ce paragraphe, il me semble que j'ai fait quand
même une erreur : je les utilise SUCCESSIVEMENT (d'abord htmlspecialchars
pour un affichage correct, et ensuite mysql_real_escape_string pour
l'insertion dans la table), alors que, si je comprends bien, faudrait
pas... Mais pour l'instant, je n'ai pas vu de dysfonctionnement. Cela dit,
je veux bien changer s'il ya des risques d'incohérences.
Je me suis aperçue aussi que j'avais besoin de la fonction
html_entity_decode (je n'ai pas accès à htmlspecialchars_decode , notre
hébergeur ayant visiblement reporté aux calendes grecques le passage à
PHP5...), lorsque je lis des données dans la base pour générer des
courriels avec la fonction mail (notification de l'acceptation ou du refus
des demandes).
Je termine en te proposant un document de référence sur le sujet, par
http://conf.phpquebec.com/slides/2005/mastering-php-security.pdf
Je vais voir ça !
Merci beaucoup pour ton aide et merci également à Patrick.
--
Pascale
Continuer la lecture sur narkive:
Loading...