在我的 CMS 应用程序中,管理用户可以通过由HTMLPurifier过滤的所见即所得编辑器添加 HTML 内容。我现在想添加留言板功能。我计划使用没有白名单的Zend StripTags 过滤器来删除所有 HTML,然后使用 Zend 的BBCode或Textile解析器提供丰富的标记。
这些是我的问题:
StripTags
如果我没有白名单,XSS 可以通过吗?- 添加 BBCode 或 Textile 作为输出解析器是否会重新引入 XSS 的可能性?
在我的 CMS 应用程序中,管理用户可以通过由HTMLPurifier过滤的所见即所得编辑器添加 HTML 内容。我现在想添加留言板功能。我计划使用没有白名单的Zend StripTags 过滤器来删除所有 HTML,然后使用 Zend 的BBCode或Textile解析器提供丰富的标记。
这些是我的问题:
StripTags
如果我没有白名单,XSS 可以通过吗?在 SO 上阅读了关于 Markdown 的帖子以及在该帖子的答案中链接的另一篇文章之后,似乎将 XSS 重新引入文档不仅是可能的,而且是微不足道的。为了安全起见,我需要通过HTMLPurifier运行内容,作为输出过滤器链中的最后一步。因为我关心HTMLPurifier作为输出过滤器的性能,所以我正在考虑使用Wibble。
这仍然没有回答第一个问题,但就我而言,这一步是不必要的。
当我尝试使用它们时,我发现 Zend 的 BBCode 和 Textile 非常糟糕。我改为使用PHP Markdown。此外,Wibble似乎还没有准备好生产。
我在数据库中使用了两列:content
和html
. 该content
列包含用户提交的文本。保存记录时,我使用PHP Markdowncontent
转换为 HTML ,通过HTMLPurifier传递它,然后将该值保存到列中。我不会以这种方式转换所有观点。html
实施细节
我把PHP Markdown放在这里:library/markdown.php
. 在我的活动记录模型中Zend_Db_Table_Row_Abstract
,我使用_insert()
和_update()
钩子在保存记录之前处理值:
// prepare html based on the content
require_once 'markdown.php';
$flt = new My_Filter_HtmlPurifier();
$this->html = $flt->filter(Markdown($this->content));
这是我的HTMLPurifier过滤器:
/**
* Based on examples from http://blog.astrumfutura.com/archives/365-Example-Zend-Framework-Blog-Application-Tutorial-Part-8-Creating-and-Editing-Blog-Entries-with-a-dash-of-HTMLPurifier.html
*/
require_once 'HTMLPurifier.includes.php';
require_once 'HTMLPurifier.autoload.php';
class My_Filter_HtmlPurifier implements Zend_Filter_Interface
{
/** @var HTMLPurifier */
protected $_htmlPurifier;
public function __construct($options = null)
{
// set up configuration
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.DefinitionID', 'My HTML Purifier Filter');
$config->set('HTML.DefinitionRev', 3); // increment when configuration changes
// $config->set('Cache.DefinitionImpl', null); // comment out after finalizing the config
// Doctype
$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
// Add support for object (flash) tags
$config->set('HTML.SafeObject', true);
$config->set('Output.FlashCompat', true); // IE Support
// Custom Filters
// Add support for iframes - YouTube, Vimeo...
$config->set('Filter.Custom', array(new HTMLPurifier_Filter_MyIframe()));
// Add support for anchor targets
$config->set('Attr.AllowedFrameTargets', array('_blank', '_self', '_target', '_top'));
// configure caching
$cachePath = CUST_APP_PATH . '/../cache/htmlpurifier';
if (!is_dir($cachePath)) {
mkdir($cachePath, 0700, true);
}
$cachePath = realpath($cachePath);
$config->set('Cache.SerializerPath', $cachePath);
// allow for passed-in options
if (!is_null($options)) {
//$config = HTMLPurifier_Config::createDefault();
foreach ($options as $option) {
$config->set($option[0], $option[1], $option[2]);
}
}
// create the local instance
$this->_htmlPurifier = new HTMLPurifier($config);
}
public function filter($value)
{
return $this->_htmlPurifier->purify($value);
}
}