【问题标题】:Forbid script tags and event listeners in jqte jQuery text editor using htmlpurifier使用 htmlpurifier 在 jqte jQuery 文本编辑器中禁止脚本标签和事件侦听器
【发布时间】:2016-01-12 19:42:48
【问题描述】:

我正在使用 jqte 给用户一个 cms 我为他们的内容写了一些所见即所得。 为了公开输出内容,我使用 htmlPurifier 所以没有办法,编辑会伤害网站的访问者。

他们可以放置

<button onclick="alert('this sux')">klick me</button>

在 textarea 中,下一个用户将找到一个工作按钮。

<script>evilcode</script>

甚至被执行。

有没有人在我之前处理过这个问题并且可以在这里给我一个优雅的解决方案的提示?

【问题讨论】:

  • 在服务器上对其进行清理是最常见的方法。任何人都可以操纵发送到服务器的内容,这是唯一安全的地方
  • 我在服务器上没有问题,当然我可以将所有 html/js 更改为没有 html/js,但我宁愿这样做让 jqte 完好无损。
  • 不确定大部分评论是什么意思
  • jqte 基于使用一些标签并对其进行解释。如果我对输入进行剥离标记(或以其他方式“取消编码”),则所见即所得的功能将丢失。我想,有一种方法可以手动过滤所有事件监听器,并为允许的标签等创建一个白名单。我只是想可能有人在我之前经历过这个。
  • 你不strip tag...你消毒...大不同

标签: javascript jquery wysiwyg htmlpurifier jqte


【解决方案1】:

我要说的是,当您将先前提交的数据加载到表单中时,输出周围没有htmlspecialchars() - 不过,您应该这样做,因为 它仍然是 text 用于 textarea。您的所见即所得将文本解释为 HTML,但不要将其与实际 HTML 混淆。 :)

作为安慰,您知道这种混淆非常普遍 (it keepshappening),而且有很多很多人的问题与您描述的完全一样。

让我们看一下工作流程以及可能出错的地方:

问题工作流程

当有人将 &amp;lt;tag&amp;gt; 写入您所见即所得字段中的富文本并加载所见即所得时,编辑器会看到有人想将 HTML &amp;lt;tag&amp;gt; 放入消息中。

当有人将粗体文本写入富文本时,编辑器会看到有人想将 HTML &lt;b&gt;bold text&lt;/b&gt;(或类似的)放入消息中。

同时,在后台,文本&amp;amp;lt;tag&amp;amp;gt; &amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt;(或其他)被存储在textarea中。为了在 HTML 上下文中将文本保留为 text,它使用 HTML 编码进行编码,不可见地将其转换为 &amp;amp;lt;tag&amp;amp;gt; &amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt;

但是,当您按下提交按钮时,文本区域 (&amp;amp;lt;tag&amp;amp;gt; &amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt;) 的 文本 将发送到您的服务器,因为表单数据本身当然不是 HTML 编码的(它不是嵌入在 HTML 中)- 它只是一组键和值,而您想要 textarea 的值。

现在,当您在服务器端应用程序中构建 HTML 以再次加载消息以进行进一步编辑时,您希望字段的 进行 HTML 编码,因为您正在将该值放入 HTML 上下文中。您之前所做的是创建 &lt;textarea&gt;&amp;lt;tag&amp;gt; &lt;b&gt;bold text&lt;/b&gt;&lt;/textarea&gt;,它将 HTML 放入 HTML 上下文中。在基本上所有浏览器中,这使得 textarea 采用 value &lt;tag&gt; &lt;b&gt;bold text&lt;/b&gt;。哎哟! (想象一下,如果有人将&lt;/textarea&gt; 作为其原始消息的一部分!)

令所有人感到困惑的是,所见即所得的编辑器很不幸地擅长在那里显示您想要的大致内容。对于大多数用例,您甚至不会注意到差异,这就是此错误如此普遍的原因。

但是,在构建页面的 HTML 时,您实际上想要构建 &lt;textarea&gt;&amp;amp;lt;tag&amp;amp;gt; &amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt;&lt;/textarea&gt;。这使得 textarea 具有 value &amp;amp;lt;tag&amp;amp;gt; &amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt; - 这正是你想要的。

你的Current Solution,以及它为什么会中断

您当前的解决方案通过htmlspecialchars_decode() 运行提交的文本,这会将&amp;lt;tag&amp;gt; 变成&amp;lt;tag&amp;gt;,从而让HTML Purifier 消除它。您不再需要担心 &amp;lt;tag&amp;gt; 在所见即所得的上下文中被解释为 &amp;lt;tag&amp;gt;

但是,很遗憾你有两个问题:

1) 如果没有 HTML Purifier 剥离它们,人们将无法再提交关于标签的消息。根据您的文本区域的用例,这可能不是问题。也许您不希望人们能够提交像 If you're making your own website, you can use &amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.js" language="javascript"&amp;gt; instead of hosting the jquery.js yourself 这样的 HTML 消息 - 使用您当前的解决方案,这样的消息将被 HTML Purifier 清理为 If you're making your own website, you can use instead of hosting the jquery.js yourself

2) 更危险,人们仍然可以黑你!尝试将 text &amp;amp;lt;script&amp;amp;gt;alert(1);&amp;amp;lt;/script&amp;amp;gt; 写入您的编辑器(以便编辑器将您要提交的 HTML 视为&amp;amp;lt;script&amp;amp;gt;alert(1);&amp;amp;lt;/script&amp;amp;gt;)并点击提交。您的解决方案会将其转换为 &amp;amp;lt;script&amp;amp;gt;alert(1);&amp;amp;lt;/script&amp;amp;gt;,然后您将其放入您的 &lt;textarea&gt;,然后不幸的是您又回到了原点。

实际解决方案

删除您的htmlspecialchars_decode() 解决方案(但要保持净化!),而是将htmlspecialchars() 放在您的输出周围。您的所见即所得仍然可以工作,并且您不会再绕过 HTML Purifier 的卫生。

【讨论】:

  • 如果这个答案令人困惑,这里是我两年前给出的一个相同问题的答案,写起来可能不太容易混淆:stackoverflow.com/a/26128263/245790
  • 这是我在这里得到的最好和最令人困惑的答案之一。非常感谢!
  • htmlspecialchars(或 htmlentities)适用于前端输出。但在所见即所得编辑器中,您的“hack”<script>alert(1);</script>变为 并因此在存储时在下一轮卫生循环中被丢弃。我很高兴我现在不需要我的解决方案来包含/解释/显示 html 标签。
【解决方案2】:

jqte 屏蔽标签所以

<

变成

&lt;

并被 HTMLpurifier 遗漏。因此,在您净化之前,您需要解码所有 html 掩码。你可以这样做

htmlspecialchars_decode($string, ENT_HTML5);

这是我的完整类,你可以在其中抛出字符串或数组,前提是你已经安装了 htmlpurifier(即使用 composer)

class cleanWysiwyg
{
    private $allowTags = array('b','i','u');
    private $purifier;

    public function __construct()
    {
          $config = HTMLPurifier_Config::createDefault();
          $config->set('HTML.AllowedElements', $this->allowTags );
          $this->purifier = new HTMLPurifier($config);
    }

      public function cleanup ( &$dirty )
      {

        if ( !is_array($dirty) )
          {
        /*do this to prevent some clever workarounds enabled by wysiwyg or bored coders*/
        $dirty = htmlspecialchars_decode($dirty, ENT_HTML5); 
            $dirty = $this->purifier->purify( $dirty );
            return;
          }
          /*if we have an array we call ourselfes for each element*/
        foreach ( $dirty as &$element ){
          $this->cleanup($element);
        }
      }
}

用作急救但仍然可以破解,请参阅标记为解决方案的答案。 留下这个答案是为了使它更容易作为解决方案的有用上下文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多