0

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

然而,他们可以放置

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

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

<script>evilcode</script>

甚至被执行。

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

4

2 回答 2

1

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

作为安慰,请知道这种混乱非常普遍(它一直在 发生),并且有很多很多人的问题与您描述的完全一样。

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

问题工作流程

当有人<tag>在加载 WYSIWYG 的情况下写入 WYSIWYG 字段中的富文本时,编辑器会看到有人想要将 HTML&lt;tag&gt;放入消息中。

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

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

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

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

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

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

当前的解决方案,以及它为什么会崩溃

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

但是,不幸的是,您有两个问题:

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

2) 更危险的是,人们仍然可以攻击你!尝试将文本 &lt;script&gt;alert(1);&lt;/script&gt;写入您的编辑器(以便编辑器看到您要提交的HTML&amp;lt;script&amp;gt;alert(1);&amp;lt;/script&amp;gt;)并点击提交。您的解决方案将把它变成&lt;script&gt;alert(1);&lt;/script&gt;,您将把它放入您的<textarea>,然后不幸的是您又回到了原点。

实际解决方案

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

于 2016-01-23T11:32:08.793 回答
0

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);
        }
      }
}

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

于 2016-01-15T20:26:57.787 回答