Est-ce que strip tags() est vulnérable aux attaques de scripting?

Est-il connu XSS ou autre attaque que fait passé une

$content = "some HTML code";
$content = strip_tags($content);

echo $content;

?

le manuel a un avertissement:

cette fonction ne modifie aucun attribut sur les balises que vous autorisez en utilisant allowable_tags, y compris les attributs style et onmouseover qu'un utilisateur malveillant peut abuser lors de l'affichage du texte qui sera montré à d'autres utilisateurs.

mais cela est lié à l'utilisation du paramètre allowable_tags seulement.

sans permis tags set , est strip_tags() vulnérable à toute attaque?

Chris Shiflett semble dire que c'est sûr:

Use Solutions Matures

dans la mesure du possible, utilisez des solutions existantes éprouvées au lieu d'essayer de créer les vôtres. Des fonctions comme strip_tags() et htmlentities() sont de bons choix.

est-ce correct? Veuillez, si possible, citer des sources.

je connais HTML purifier, htmlspecialchars() etc.- Je suis pas à la recherche de la meilleure méthode pour assainir HTML. Je veux juste savoir à propos de cette question spécifique. C'est une question théorique qui a été soulevée ici .

référence: strip_tags() implémentation dans le code source PHP

44
demandé sur Community 2011-04-26 13:40:14

4 réponses

comme son nom l'indique, strip_tags devrait supprimer toutes les balises HTML. La seule façon de le prouver est d'analyser le code source. L'analyse suivante s'applique à un appel strip_tags('...') , sans un second argument pour les tags sur liste blanche.

tout d'abord, une théorie sur les balises HTML: une balise commence par un < suivi de caractères non-blancs. Si cette chaîne commence par un ? , il ne doit pas être écrit . Si ce string commence par un !-- , il est considéré comme un commentaire et le texte suivant ne doit pas être interprété. Un commentaire est terminé par un --> , à l'intérieur d'un tel commentaire, des caractères comme < et > sont autorisés. Les attributs peuvent apparaître dans les tags, leurs valeurs peuvent éventuellement être entourées d'un caractère de citation ( ' ou " ). Si une telle citation existe, elle doit être fermée, sinon si un > est rencontré, l'étiquette n'est pas fermée.

le code <a href="example>xxx</a><a href="second">text</a> est interprété dans Firefox comme:

<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>

la fonction PHP "1519610920 strip_tags est référencée dans ligne 4036 de ext/standard/string.c . Cette fonction appelle la fonction interne php_strip_tags_ex .

il existe deux tampons, l'un pour la sortie, l'autre pour"Inside HTML tags". Un compteur nommé depth tient ouvert le nombre de consoles d'angle ( < ).

La variable in_q contient le caractère de citation ( ' ou " ) le cas échéant, et 0 autrement. Le dernier caractère est stocké dans la variable lc .

les fonctions contiennent cinq États, trois sont mentionnés dans la description au-dessus de la fonction. Sur la base de cette information et du corps de fonction, les états suivants peuvent être dérivés:

  • L'État 0 est l'état de sortie (aucune étiquette)
  • État 1 signifie que nous sommes à l'intérieur d'une normale balise html (le tag de la mémoire tampon contient < )
  • état 2 signifie que nous sommes à l'intérieur d'une étiquette php
  • état 3: Nous sommes venus de l'état de sortie et avons rencontré les caractères < et ! (le tampon d'étiquette contient <! )
  • État 4: à l'intérieur de commentaire HTML

nous devons juste faire attention qu'aucune étiquette ne peut être insérée. Qui est, < suivi d'un caractère non-blanc. ligne 4326 vérifie un cas avec le caractère < qui est décrit ci-dessous:

  • Si entre guillemets (par exemple <a href="inside quotes"> ), le caractère < est ignoré (supprimé de la sortie).
  • si le caractère suivant est un caractère d'espace, < est ajouté au tampon de sortie .
  • si en dehors d'une étiquette HTML, l'état devient 1 ("étiquette HTML intérieure") et le dernier caractère lc est défini à <
  • Sinon, si à l'intérieur de la balise HTML, le compteur nommé depth est incrémenté et le caractère ignoré.

si > est respecté alors que l'étiquette est ouverte ( state == 1 ), in_q devient 0 ("pas dans un devis") et state devient 0 ("pas dans une balise"). le tampon d'étiquette est éliminé.

Les vérifications D'attributs

(pour les caractères comme ' et " ) sont effectuées sur le tampon d'étiquette qui est éliminé. Donc la conclusion est:

strip_tags sans une balise de liste blanche est sans danger pour l'inclusion à l'extérieur de tags, pas de balise sera autorisé.

par "tags extérieurs", je veux dire pas dans tags comme dans <a href="in tag">outside tag</a> . Le texte peut contenir < et > cependant, comme dans >< a>> . Le résultat N'est pas valide HTML bien, < , > et & doivent encore être échappés, en particulier le & . Cela peut être fait avec htmlspecialchars() .

la description de strip_tags sans argument de la liste blanche serait:

S'assure qu'aucune balise HTML n'existe dans la chaîne retournée.

45
répondu Lekensteyn 2011-04-29 19:42:25

Je ne peux pas prédire les exploits futurs, d'autant plus que je n'ai pas regardé le code source PHP pour cela. Cependant, il y a eu des exploits dans le passé en raison de navigateurs acceptant des étiquettes apparemment invalides (comme <s"151920920"cript> ). Donc, il est possible que dans le futur quelqu'un pourrait être en mesure d'exploiter le comportement étrange du navigateur.

qu'à part, envoyer la sortie directement au navigateur comme un bloc complet de HTML ne devrait jamais être non sécurisé:

echo '<div>'.strip_tags($foo).'</div>'

Toutefois, ce n'est pas sûr:

echo '<input value="'.strip_tags($foo).'" />';

parce qu'on pourrait facilement terminer la citation via " et insérer un gestionnaire de script.

je pense qu'il est beaucoup plus sûr de toujours convertir < en &lt; (et le même avec des citations).

10
répondu Matthew 2011-04-26 16:54:11

Strip tags est parfaitement sûr - si tout ce que vous faites est la sortie du texte au corps html.

il n'est pas nécessairement sûr de le mettre dans des attributs mysql ou url.

2
répondu kemus 2011-04-26 10:08:48

selon cet outil en ligne , cette chaîne sera" parfaitement " échappée, mais le résultat est un autre méchant!

<<a>script>alert('ciao');<</a>/script>

dans la chaîne , les" vraies "étiquettes sont <a> et </a> , car < et script> ne sont pas des étiquettes seules.

j'espère que je me trompe ou que C'est juste à cause d'une ancienne version de PHP, mais c'est mieux de vérifier dans votre environnement.

2
répondu Ludovico Grossi 2017-11-02 20:53:19