Zend Framework XSS-фильтрация ввода / вывода: полосы, текстиль, BBCode - PullRequest
1 голос
/ 13 октября 2011

В моем приложении CMS пользователи-администраторы могут добавлять HTML-контент через редактор WYSIWYG, который фильтруется с помощью HTMLPurifier . Теперь я хочу добавить функциональность доски объявлений. Я планирую использовать Zend StripTags Filter без белого списка, чтобы удалить весь HTML, а затем обеспечить расширенную разметку с помощью Zend BBCode или Textile парсеров.

Это мои вопросы:

  1. Может ли XSS пройти через StripTags, если у меня нет белого списка?
  2. Добавляет ли BBCode или Textile в качестве выходного синтаксического анализатора возможность XSS?

1 Ответ

2 голосов
/ 17 октября 2011

После прочтения поста о Markdown здесь на SO и другой статьи, связанной в ответе на этот пост , кажется, что повторное введение XSS в документ не только возможно, но итривиальный.Чтобы быть в безопасности, мне нужно будет запустить контент через HTMLPurifier в качестве шага final в цепочке фильтров output .Поскольку я обеспокоен производительностью HTMLPurifier в качестве выходного фильтра, я пытаюсь использовать вместо него Wibble .

Это все еще оставляет первый вопрос без ответа, но вв моем случае, этот шаг будет ненужным.


Я обнаружил, когда пытался их использовать, что Zend BBCode и Textile ужасно глючат.Вместо этого я использовал PHP Markdown .Кроме того, Wibble , похоже, еще не готов к работе.

В своей базе данных я использовал два столбца: content и html.Столбец content содержит текст, отправленный пользователем.При сохранении записи я конвертирую content в HTML с PHP Markdown , пропускаю его через 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);
    }
}
...