Aller au contenu

htmlspecialchars et sécurité


nono

Sujets conseillés

Me revoici avec une question sur phpMyAnnu.

A la base, il y avait un problème avec la recherche. Les mots clés devaient être affichés en gras avec la ligne : { return eregi_replace($mots,"<strong>\0</strong>",$chaine); }

Seulement, ça affichait les balises strong autout du mot clé au lieu de les mettre en gras.

Bref, en fouillant sur le forum du Hub, j'ai trouvé une solution qui consiste à remplacer echo htmlspecialchars($message); par echo $message; dans la fonction qui affiche les résultats de la recherche. Je l'ai fait, et youpii, le tour était joué, tout était parfait.

Sur le forum de l'éditeur du script, on m'a dit ceci :

le fait de supprimer le htmlspecialchars ouvre une porte grosse comme une maison a des failles de securites.

Des pirates vont pouvoir afficher n'importe quoi comme code html

Ma question est la suivante : est-ce vrai, ou pas ? Si oui, que dois-je faire pour palier ce problème ?

Merci d'avance...

Nono

Lien vers le commentaire
Partager sur d’autres sites

Oui, c'est vrai (le HTML n'est pas potentiellement dérangeant, si ce n'est un possible allongement de ton design, mais ça laisse la possibilité de poster du JavaScript).

Pour contourner le problème, tu pourrais utiliser htmlspecialchars dans la fonction même, du genre :

{ return eregi_replace($mots,"<strong>\0</strong>",htmlspecialchars($chaine)); }

Lien vers le commentaire
Partager sur d’autres sites

A mon avis si un hacker va mettre du Javascript ou autre code dans le message di style

<script> ... </SCRIPT>

Avec echo $message, le navigateur va confondre le code ci-dessus avec un script inséré dans la page, et va donc l'exécuter ! :blink:

Tandis que si l'on emploie echo htmlspecialchars($message), le code va être affiché à l'écran sans exécution, puisque les " et autres caractères sensibles auront été remplacés.

Une autre solution serait pour moi de vérifier après avoir rempli le formulaire si le champ contient des balises HTML ou non :whistling:

Donc pour éviter les ennuis, autant utiliser l'une ou l'autre méthode :unsure:

Lien vers le commentaire
Partager sur d’autres sites

C'est juste, lorsque tu affiches des données provenant d'une source peu fiable (par exemple l'occurrence un visiteur), tu t'expose à une attaque par vol de cookie ou autres techniques XSS (Cross site scripting)...

L'utilisation de htmlspecialchars empêche purement et simplement l'utilisation de balises HTML active...car elle transforme les caractères : & , " , ' , < et > en leurs entités respectives. Cela a pour effet d'afficher ces caractères au lieu qu'ils soient interprétés par les navigateurs.

Pour ne pas être aussi restrictif, on peut utiliser la fonction strip_tags qui permet d'enlever les tags indésirable et de laisser ceux que tu désire... par exemple :

echo strip_tags($message,'<b><strong><i><em>');

Permet les balises mentionnées comme deuxième paramètre...et enlève tous les commentaires et autres balises (entre autres celle à risque comme <script>). Mais si les balises sont mal formées, plus de texte que prévu ne sera enlevé...par exemple :

<strong Mon texte</strong>

Retournerait une chaine vide... regarde parmi les commentaires du manuel, il y a également des fonctions intéressantes créées par les utilisateurs ;)

Lien vers le commentaire
Partager sur d’autres sites

Ok je vois...

mais bon, le truc, c'est que la fonction sert à afficher en gras les mots de la recherche. Si le petit hackeur entre un script dans le champ de recherche, ça ne fait rien, non ?

et puis pour soumettre un site, les entrées qu'il saisit dans le formulaire de soumission ne sont pas validées de suite, c'est moi qui décide de les accepter ou non. Donc normalement, s'il s'amuse à rentrer du script, je devrais le voir dans les champs qu'il a rempli, je me trompe ?

Bref, comme je ne connais pas grand chose en php, j'ai besoin d'être éclairé là-dessus. J'attends la réponse à ces questions avant de toucher au code de la page.

Sinon captain_torche, si j'ai bien compris, je dois remplager ma ligne par celle que tu me propose (comme je l'ai dit, je n'y connais rien, j'aime le préfabriqué :rolleyes: ) ?

Merci à vous

Lien vers le commentaire
Partager sur d’autres sites

Si c'est justement lorsque tu affiches (c'est en général le but du stockage de données) des données qu'un visiteur a envoyées que le risque de faille XSS est présent... je ne veux pas donner d'exemple précis ici (de code) pour des raisons évidentes... mais imagine que tu mettes un JavaScript qui envoie le contenu du cookie de ton site (si tu en utilises un) dans ce champ... si tu envoie cette page sans prêter garde à la sécurité des données qui y sont affichées, ce Javascript sera exécuté à chaque fois que quelqu'un utilisera la page ou ce texte s'affiche...et le pirate récupérera les cookies de ces utilisateurs.

Y compris lorsque toi, avec ton cookie permettant d'accéder aux fonctions d'administration de ton site (par exemple), tu afficheras cette page... lorsque le pirate aura ton cookie, il pourra soit l'utiliser directement (cookie avec peu de sécurité), soit en extraire des informations pour pirater ton serveur... il y a d'autres méthodes, mais c'est la plus courante...

Maintenant, si tu vérifies en amont, lorsque l'utilisateur entre les données dans la base, tu n'a pas besoin de t'en soucier à l'affichage...enfin c'est relatif, imagine qu'un pirate trouve un moyen d'utiliser une faille dans tes requêtes (SQL) sur la base de donnée et qu'il l'utilise pour insérer des données exploitant une faille XSS (comme l'exemple précédent)...tu te retrouves avec le même problème (à moins de sécuriser à l'affichage également). Cela peut paraître beaucoup de sécurité, mais dans certains cas.

Dans le cadre dun système simple, auquel tu ne laisse accès quà des personnes sélectionnées tu na pas à te soucier en détails de ces problèmes (un minimum est nécessaire quand même), dès que laccès est public et que les données sont sensibles cest une nécessité de sen soucier.

Et, ce nest pas pour te décourager, les pirates ne se limitent pas à ceci, il suffit de voir le nombre élevé de mises à jour de sécurité pour des systèmes de forums comme phpBB :S

Lien vers le commentaire
Partager sur d’autres sites

Ok ok... tu me fais peur avec tout ça... Je vais être un peu plus précis.

Les seuls endroits où l'on peut entrer un script, c'est dans le formulaire de recherche ou dans les champs pour soumettre un site. Comme je vérifie toutes les entrées quand quelqu'un soumet un site, il m'est possible de voir si un champ comporte un script.

Est-il possible que quelqu'un puisse entrer un script et que je ne puisse pas le voir dans le panneau d'administration ?

Autre question, le htmlspecialchars() pour la recherche concernait les mots clés à mettre en gras dans le listing des résultats. Si quelqu'un entre un script dans le formulaire de recherche, normalement, ça ne fait rien non ? (dites-moi si je me trompe).

Sinon, pour soumettre un site, il y a des fonctions de vérifications de ce type (avec un des pb htmlspecialchars) :

function email_valide($email,$inc = false)
//verifie la validite d'une adresse email : syntaxe + non vide
{
$message = "<br />";
if (empty($email))
{
 $message .= "Le champ adresse email ne peut être vide !\n<br />\n";
 $email_ok = false;
}
else //l'email a ete entree, on la verifie
{
 //verification de la syntaxe
 $email_ok = eregi("^[_\.0-9a-z-]+@([0-9a-z-]+\.)+[a-z]{2,4}$",$email);  
 //verification du domaine
 if(TEST_MAIL)
 //on doit se connecter pour verifier l'existance du domaine
 {  
 list($user, $domaine) = split("@", $email, 2);
 $domain_ok = _AT_checkdnsrr($domaine, "MX");
 }
 else
 //si on travaille en local, on ne se connecte pas pour verifier le domaine
 { $domain_ok = true; }
}
if (!$email_ok || !$domain_ok)
{
 $message .= "L'adresse email \"$email\" n'est pas valide !\n<br />\n";
 $message .= "<br /><br />\n";
 $message .= "<a href=\"java script:history.go(-1);\">Retour au formulaire</a>\n";
 echo htmlspecialchars($message);
 if ($inc) //si on peut faire die() (-> admin)
 include("after.php");    
 exit;
}
return true;
}

C'est bien joli tout ça, mais le htmlspecialchars() à la fin fait afficher tout le code html avec les balises... dans le cas où l'adresse n'est pas entrée ou est fausse.

Dans ces cas-là, j'ai tout simplement enlevé les htmlspecialschars et j'ai laissé "echo $message; Voilà pour les précisions. Merci de me dire si c'est ok ou pas.

PS : TheRec, vive la suisse ^_^

Lien vers le commentaire
Partager sur d’autres sites

Je vais résumer, si tu affiche des données qui ont été a quelque moment que ce soit été entrées ou même modifiées par un utilisateur, c'est à toi de les vérifier... donc lorsque quelqu'un recherche un mot et que tu fais ceci par exemple :

echo 'Résultats pour la recherche sur "'.$_GET['keywords'].'"';

Tu laisses la possibilité à un utilisateur d'entrer des données malicieuses (un morceau de Javascript) ... Si par contre tu utilise la fonction htmlspecialchars ou strip_tags cela règle le problème...

echo 'Résultats pour la recherche sur "'.strip_tags($_GET['keywords']).'"';

Pour le code que tu présente...fait ceci ainsi ...pour les dernières lignes :

$message .= "L'adresse email \"".htmlspecialchars($email)."\" n'est pas valide !\n<br />\n";
$message .= "<br /><br />\n";
$message .= "<a href=\"java script:history.go(-1);\">Retour au formulaire</a>\n";
echo $message;

La seule données sensible est celle donnée par l'utilisateur...(les <br/> sont de ton propre chef, l'utilisateur ne peut pas intervenir sur cette partie)

P.S. : Serais-tu un de mes compatriotes ? :D

Lien vers le commentaire
Partager sur d’autres sites

Ok, je vois ce que tu veux dire.

C'est quand même pas toujours facile quand on ne comprend pas :blush: Merci de ton aide en tous cas.

Pour ce qui s'agit du mail, je m'en vais tout de suite faire le changement. Je me baserai sur ce modèle pour faire les autres entrées. Par contre, pour le truc de la recherche, je vais tenter de me plonger dedans et faire quelque chose. :wacko:

Je te dirai si comment ça se passe.

Ps : Voui !! je suis un de tes compatriotes, mais je suis à l'étranger. Tu peux pas savoir ce que je donnerais pour une bonne fondue :P

Lien vers le commentaire
Partager sur d’autres sites

Hello, me revoici.

désolé du temps de réponse, mais j'avais pas mal de taf.

Est-ce que quelqu'un de super sympa (il n'y a que ça ici de toutes façons) pourrait m'expliquer ce petit truc ? Ca concerne le formulaire de recherche.

<?php printf ("%d catégorie(s) et %d site(s) trouvé(s) pour \"%s\" en %.3f s\n",$nb_cats_trouvees,$nb_sites_trouves,stripslashes(htmlspecialchars($mots)),$time_search); ?>

Je ne connais toujours pas le php, mais j'aimerais savoir si j'ai quand même compris ça. il me semble que le stripslashes(htmlspecialchars($mots)) se réfère aux mots recherchés, mais je sais que \"%s\" affiche le ou les mots que l'on a tapé pour la recherche. Quelqu'un pourrait éclairer ma lanterne ? :blink:

Merci d'avance. :D

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Je te conseille de relire le manuel à propos de la syntaxe de sprintf (qui est la même que printf).

Dans ton cas, %s représente une chaîne de caractères et comme c'est la troisième directive (il y a deux %d (entier signé) avant), la troisième variable spécifiée en paramètre (soit stripslashes(htmlspecialchars($mots))) remplacera ce %s ...

Le fait qu'il soit entouré de deux \" résulte du fait que pour afficher le caractère " dans une chaine de caractères délimitée par des " (double quote) il faut échapper ce caractère..avec \.

Tu pouvais également écrire cette ligne d'une autre manière :

echo $nb_cats_trouvees.'catégorie(s) et '.$nb_sites_trouves.' site(s) trouvé(s) pour "'.htmlspecialchars(stripslashes($mots)).'" en '.number_format($time_search,3).' s\n';

Cela revient au même ! C'est simplement une autre manière de présenter une chaîne de caractères. Note que j'ai inversé "htmlspecialchars" et "stripslashes" d'ordre, car il est plus logique de d'abord enlever les "\" qui ont été ajouté juste pour pouvoir enter ces données dans la base et les récupérer sans problème et ensuite convertir les caractères spéciaux en entités (pour la sécurité).

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à tous, je viens me greffer sur ce fil car ce ont je souhaite parler se rapproche énormément du sujet abordé ici...

Comment ça marche ici pour la sécurité??? Parce qu'on cherche a éviter les sources d'ennuis (du style...code php ou javascript :blush: ) et ici, on propose fièrement des quantités de code!!!

En fait, je cherche à faire la même chose, c'est à dire éventuellement afficher du code sans risque pour mon site!!!! Le but définitif, c'est d'éviter d'utiliser des Regex où je pourrais omettre la possibilité d'utiliser des caractères qui enverrait l'internaute sur les roses... Un exemple par exemple:

L'internaute souhaite enregistrer l'adresse suivante:

13 rue de la mairie

Lieu dit "Trou Perdu"

13666 PasDeBol

Je pensais faire une Regex du style

preg_match('!^[a-z0-9._-]+$!', $Adresse)

et l'adresse ne sera pas correcte selon ma regex (elle est un peu violente mais c'est pour l'exemple :P )Je peux éventuellement l'élargir mais il doit bien y avoir un moyen de prendre tout en compte (comme ici) et l'afficher sans prendre de risque (comme ici)

addslashes : ça laisse passer pas mal de trucs...

htmlentities : ça déforme tout (et en utilisant html_entity_decode, je pense qu'on revient au même problème)

htmlspecialchars : comme htmlentities...

Si jamais quelqu'un à un morceau de réponse, ils sont les bienvenus (lui et le morceau de réponse ;) )

Lien vers le commentaire
Partager sur d’autres sites

Merci pour le lien captain_torche...

Mais ça ne me donne pas la formule (magique???) du style:

$Prenom=Yapludesouci($_POST['Prenom']);

Non, je rigole, c'est très instructif (je suis déjà un adepte de phpsecure ;) ) mais je me demandais juste si quequ'un n'avait pas sous le bras une longue instruction qui gère tout toute seule :P . Mais bon, visiblement, je vais devoir m'y coller!!!! :unsure:

Lien vers le commentaire
Partager sur d’autres sites

Tu devrais au moins utiliser htmlspecialchars():

$Prenom=htmlspecialchars($_POST['Prenom'];

Cela permet d'éviter d'afficher des balises <script> lorque tu afficheras le prénom. Elles s'afficheront <script>, ce qui ne sera pas interprété par le navigateur.

Dan

Lien vers le commentaire
Partager sur d’autres sites

Salut Dan,

Mais toi, tu les affiches bien les balises <script> sur ce forum, et ça a pas l'air de te poser plus de problèmes que ça visiblement... :whistling:

Merci

Lien vers le commentaire
Partager sur d’autres sites

Ce ne sont pas des balises venant de la BDD, ça

Bah, nos messages sont bien stockés dans une base de donnée, non??? Du coup, ils viennent de la BDD quand on souhaite les afficher...

Quant au code que tu as mis, étant donné que je ne connais rien (mais alors vraiment rien!!! :blush: ) en JavaScript, et bien je ne vois pas ce qui le différencie d'un autre :lol: .

Lien vers le commentaire
Partager sur d’autres sites

Tout simplement que si le code venant de la BDD était inséré "tel quel" dans la page, tu aurais eu une belle alerte JavaScript ;)

Là, comme il y a un traitement htmlspecialchars() (au moins) sur les textes, tu vois une belle 'version texte', de ma tentative de pourrissement du forum ;)

Les balises que tu vois dans le source du forum, ne viennent pas de nos messages, donc il n'y a pas de danger.

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...