8795 sujets

Développement web côté serveur, CMS

Bonjour,

J'ai suivi un tuto traitant des expressions régulières qui apprend à réaliser son propre BBCode. Il faut dire que mon objectif est surtout de stocker en BDD du texte html contenant quelques balises de base (<strong>, <em>, <br />, <span>, <div>, <p>, etc.) sans guerre plus, sans définition de styles ou autres. Stocker du html très basique sous forme de BBCode, pour éviter les problèmes de sécurité (faille XSS).

Mon intention est alors de remplacer simplement les chevrons < et > par les crochets [ et ], de stocker le texte avec les crochets en BDD après lui avoir appliqué htmlspecialchars par exemple. Je transforme ensuite les crochets en chevrons, juste avant l'affichage. Cela neutralise ainsi une éventuelle injection de code avec des chevrons, mais en préservant mon texte formaté avec les crochets.

Concrètement, je fais simplement par exemple pour le texte à mettre en BDD :

$texte = str_replace("<", "[", $texte);
$texte = str_replace(">", "]", $texte);

et l'inverse à la restitution du texte pour l'afficher.

Mais je me suis vite rendu compte que cela ne résolvait pas vraiment le problème de sécurité lié à l'injection de code javascript par exemple. En effet, si le pirate a eu l'idée d'injecter son code avec les crochets à la place des chevrons, l'attaque marche... Smiley fache

Voici par exemple ce que le tuto préconise, avec la fonction preg_replace, pour mettre une portion de texte en gras :

$texte = preg_replace("#\[b\](.+)\[/b\]#isU", "<strong>$1</strong>", $texte);

Mais je voudrais faire plus simple que cela, mais un peu plus compliqué que mon idée originale, toujours avec la fonction str_replace.

Je veux écrire tout mon texte à mettre en BBD en remplaçant une balise du genre <machin> en balise [ machin ], et celle de fermeture </machin> simplement par [ / machin ]. Et à la restitution du texte, je fais l'opération inverse (j'espace exprès les caractères, car je me suis rendu compte que le BBCode du présent forum marche avec certains des mots-clefs que j'emploie, ce qui cause un problème d'affichage...).

Cela donnerait donc par exemple :

$texte = str_replace("[ strong ]", "<strong>", $texte);
$texte = str_replace("[ / strong ]", "</strong>", $texte);

deux lignes au lieu d'une comme précédemment. Mais l'avantage est que je conserve exactement mes habitudes et réflexes html, puisque je ne fais que remplacer les chevrons par les crochets et vice-versa pour l'opération inverse.

J'ai beau examiner la nouvelle solution, je ne vois pas comment il peut subsister un risque d'attaque XSS. Mais d'un autre côté, je me dis que si les "pro" et ce tuto délaissent cette solution simple pour le genre de solution mentionné, c'est qu'il doit y avoir une bonne raison qui m'échappe, et qui rendrait peu recommandable la deuxième solution.

Si oui, alors quelles raisons ? Merci de votre éclairage.
Modifié par somdina (26 Jan 2011 - 00:48)
salut

a écrit :
Stocker du html très basique sous forme de BBCode, pour éviter les problèmes de sécurité (faille XSS).


Alors, strip_tags sera ton ami.
keran a écrit :

Alors, strip_tags sera ton ami.


Euuh Smiley rolleyes , non, je pense pas qu'il sera vraiment mon ami dans ce cas-là. Pour autre chose peut-être...

Car d'après ce que j'ai compris en consultant la doc PHP que tu m'as indiquée, strip_tag supprime purement et simplement les balise HTML.

Par exemple, d'après l'exemple que donne le manuel,

'<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>'

devient :

'Test paragraph. Other text'

Alors adieu tous les paragraphes, les liens, les gras, les italiques, etc. !!! OHHH la misère !

C'est pas ça du tout que je veux faire mon ami... Smiley lol

Ce que je veux faire, c'est TRANSFORMER les balises HTML en BBCode pour pouvoir appliquer en toute tranquillité les fonctions de sécurité (entre autres htmlspecialchars , htmlentities) sur le texte sans bousiller le balisage, puisqu'il est sauvegardé en BBCode. Et à l'affichage du texte sauvegardé, je transforme le BBCode en HTML.

De toute façon (comme la réponse tardait à venir...), j'ai finalement décidé d'adopter la méthode compliquée que préconise le tuto, car je lui ai trouvé de multiples avantages sur la mienne... Je clos donc ce sujet où finalement j'ai fait question-réponse.... Autant pour moi, et Merci...
salut

a écrit :
non, je pense pas qu'il sera vraiment mon ami dans ce cas-là. Pour autre chose peut-être...


Désolé de te contredire mais strip_tags peut recevoir des params dont un qui permet de filtrer les balises à ne pas supprimer...Mais bon, peu importe.
keran a écrit :

Désolé de te contredire mais strip_tags peut recevoir des params dont un qui permet de filtrer les balises à ne pas supprimer....


Mais, justement, mon but n'est pas de supprimer la moindre balise, quelle qu'elle soit. Par conséquent, si j'utilisais strip_tags, je serais obligé de lui dire en param de laisser toutes les balises. Alors à quoi bon faire appel à lui s'il ne doit rien supprimer ? Smiley rolleyes

Je ne sais pas si tu me comprends.

Ce n'est pas pour te contredire, pour le plaisir de le faire, car très honnêtement j'ai réfléchi en long en large sur l'outil que tu me suggères, j'ai potassé la doc, mais j'ai beau tourner la question dans tous les sens, je ne vois pas comment strip_tags peut m'aider à réaliser un BBCode.

Soyons concret : donne-moi le script, avec strip_tags, pour obtenir ce BBCode par exemple:

"Je veux que [ gras] cette partie [/gras] de la phrase soit en gras."

Le problème est de réaliser une fonction qui, au moment d'afficher la chaîne, restitue ce code HTML correspondant pour le navigateur :

"Je veux que <strong> cette partie </strong> de la phrase soit en gras."

Comment tu fais cela avec strip_tags ?

Donne-moi, s'il te plaît, concrètement la solution pour ce petit exemple, et je t'assure que je saurais le faire pour toutes les autres balises. Merci Smiley smile

PS:

Ceci dit, je précise que le problème est résolu, et que ce code inspiré du tuto est plus que la solution au problème:

$texte = preg_replace("#\[gras\](.+)\[/gras\]#isU", "<strong>$1</strong>", $texte);

Pardon donc, pour le dérangement, pour avoir fait question-réponse...
Modifié par somdina (27 Jan 2011 - 00:19)