Очистка пользовательского ввода (текста) из формы от вредоносного кода в yii2.
  • 1138

Очистка текста из формы от вредоносного кода в yii2.

Автор: admin | 13 августа (Пн.) 2018г. в 14ч.01м.

Зачем нужно очищать текст из формы.

Очистка текстовых данных, которые приходят из формы является обязательным моментом в обеспечении безопасности веб приложения или сайта. Если на сайте есть форма добавления комментариев или какого-либо контента, то нужно в обязательном порядке фильтровать контент из формы перед сохранением в базе данных, чтобы исключить возможность XSS атаки на Ваш сайт.

Если на выходе нужен простой текст, то можно очистить данные от всего кода и оставить на выходе только чистый текст.Для этого можно воспользоваться функциями для очистки данных, которые есть в php, например strip_tags($str) или htmlspecialchars($str).Также можно использовать средства фреймворка yii2 и применить yii\helpers\Html::encode($content, $doubleEncode = true)

Но что делать, если нужно очистить текст не от всего кода, а только от вредоносного кода и при этом разрешить теги форматирования html.Тем более, если используется редактор WYSIWYG, например TinyMce.

Несомненно нет смысла в этом редакторе, если будет удален весь код разметки.Для фильтрации данный из формы с сохранением нужного кода и очисткой не безопасного вредоносного кода будем использовать хелпер в yii2 yii\helpers\HtmlPurifier::process($text, $config) HtmlPurifier предоставляет возможность очистки HTML от любого вредоносного кода. Стоит отметить, что этот хелпер использует HTML Purifier библиотеку.HTML Purifier - это стандартная библиотека фильтров HTML, написанная на PHP.

Применение HtmlPurifier в yii2 для очистки текста.

В данной статье рассмотрим работу именно с yii\helpers\HtmlPurifier в yii2.
Для очистки текста от вредоносного кода достаточно пропустить наш текст через метод $text = yii\helpers\HtmlPurifier::process($text, $config)

Первый параметр, который передается в метод process() - это текст, который очищаем, второй- настройки фильтров. По умолчанию HtmlPurifier::process($text, $config) уже имеет определенный настройки. Но может понадобиться внести коррективы в конфиг фильтра. Так, для поддержки html5 тегов нужно добавить такой конфиг:
$config => function ($conf) {
    $def = $conf->getHTMLDefinition(true);
    $def->addElement('mark', 'Inline', 'Inline', 'Common');
    $def->addAttribute('a', 'id', 'Text');
    $def->addAttribute('a', 'target', 'Text');
    $def->addAttribute('img', 'class', 'Text');
}

$cleanText = yii\helpers\HtmlPurifier::process($text, $config);​
Здесь мы разрешаем тег 'mark' и некоторые аттрибуты тега a и img, которые по умолчанию будут отфильтрованы.

Вот так для примера добавляет поддержку html5 тегов и нужных элементов:
$config => function ($conf) {
    $def = $conf->getHTMLDefinition(true);
    $def->addElement('section', 'Block', 'Flow', 'Common');
    $def->addElement('nav',     'Block', 'Flow', 'Common');
    $def->addElement('article', 'Block', 'Flow', 'Common');
    $def->addElement('aside',   'Block', 'Flow', 'Common');
    $def->addElement('header',  'Block', 'Flow', 'Common');
    $def->addElement('footer',  'Block', 'Flow', 'Common');

    // Content model actually excludes several tags, not modelled here
    $def->addElement('address', 'Block', 'Flow', 'Common');
    $def->addElement('hgroup', 'Block', 'Required: h1 | h2 | h3 | h4 | h5 | h6', 'Common');

    // http://developers.whatwg.org/grouping-content.html
    $def->addElement('figure', 'Block', 'Optional: (figcaption, Flow) | (Flow, figcaption) | Flow', 'Common');
    $def->addElement('figcaption', 'Inline', 'Flow', 'Common');

    // http://developers.whatwg.org/the-video-element.html#the-video-element
    $def->addElement('video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', array(
      'src' => 'URI',
      'type' => 'Text',
      'width' => 'Length',
      'height' => 'Length',
      'poster' => 'URI',
      'preload' => 'Enum#auto,metadata,none',
      'controls' => 'Bool',
    ));
    $def->addElement('source', 'Block', 'Flow', 'Common', array(
      'src' => 'URI',
      'type' => 'Text',
    ));

    // http://developers.whatwg.org/text-level-semantics.html
    $def->addElement('s',    'Inline', 'Inline', 'Common');
    $def->addElement('var',  'Inline', 'Inline', 'Common');
    $def->addElement('sub',  'Inline', 'Inline', 'Common');
    $def->addElement('sup',  'Inline', 'Inline', 'Common');
    $def->addElement('mark', 'Inline', 'Inline', 'Common');
    $def->addElement('wbr',  'Inline', 'Empty', 'Core');

    // http://developers.whatwg.org/edits.html
    $def->addElement('ins', 'Block', 'Flow', 'Common', array('cite' => 'URI', 'datetime' => 'CDATA'));
    $def->addElement('del', 'Block', 'Flow', 'Common', array('cite' => 'URI', 'datetime' => 'CDATA'));

    // TinyMCE
    $def->addAttribute('img', 'data-mce-src', 'Text');
    $def->addAttribute('img', 'data-mce-json', 'Text');

    // Еще аттрибуты для примера
    $def->addAttribute('iframe', 'allowfullscreen', 'Bool');
    $def->addAttribute('table', 'height', 'Text');
    $def->addAttribute('td', 'border', 'Text');
    $def->addAttribute('th', 'border', 'Text');
    $def->addAttribute('tr', 'width', 'Text');
    $def->addAttribute('tr', 'height', 'Text');
    $def->addAttribute('tr', 'border', 'Text');
    
}   

$cleanText = yii\helpers\HtmlPurifier::process($text, $config);
​
Для того, чтобы HtmlPurifier не удалял youtube видео iframe пишем следующий конфиг:
$config => function ($conf) {
    $conf->set('HTML.SafeIframe', true);
    $conf->set('URI.SafeIframeRegexp', '%^(http:|https:)?//(www.youtube(?:-nocookie)?.com/embed/|player.vimeo.com/video/)%');
}
$cleanText = yii\helpers\HtmlPurifier::process($text, $config);
​
Далее, чтобы не дублировать анонимную функцию целиком, буду описывать только код, что внутри нее, дабы сосредоточиться на сути.
Зачастую WYSIWYG редактор оставляет какие-то пустые теги, что засоряет наш html не нужными элементами. Для того, чтобы удалить пустые теги
мы можем установить следующий конфиг:
$conf->set('AutoFormat.RemoveEmpty', true);//удалить пары пустых тегов
$conf->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);//удалите пустой, даже если он содержит  
$conf->set('AutoFormat.AutoParagraph', true);//удалить пары пустых тегов​
Также можно заменить все относительные ссылки ссылки на абсолютные, передав заранее в конфиг базовый url:
$url = yii\helpers\Url::base();
$conf->set('URI.Base', $url);
$conf->set('URI.MakeAbsolute', true);​
Как добавить элементы мы рассмотрели, теперь рассмотрим как отфильтровать ненужные элементы.
Допустим, нам нужно удалить весь css код из текста. Делаем такой конфиг:
$conf->set('CSS.AllowedProperties', array());​
Для того, чтобы разрешить только нужные html теги пишем:
$conf->set('HTML.AllowedElements', array('p', 'div', 'a', 'br', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'ul', 'ol', 'li', 'b', 'i'));
​
Другие теги будут отфильтрованы.
Также можно запретить какие-либо атрибуты у конкретного тега:
$conf->set('HTML.ForbiddenAttributes', array('tagname.data-no-index'));​
Или пишем только разрешенные атрибуты. Остальные будут отсеяны:
$conf->set('HTML.AllowedAttributes', array('p.class', 'div.id', 'a.href'));​

Где лучше фильтровать данные из формы.

Лучше всего фильтровать данные, пришедшие из формы в модели. Для этого можно воспользоваться поведением PurifyBehavior, которое нужно подключить в массиве behaviors() в целевой модели.
Как это сделать я описал в статье "Создаем поведение yii2 PurifyBehavior для очистки данных из формы."

На этом все.

Приветствую!

Меня зовут Сергей. Я - автор этого блога.

Если Вам был полезен материал на моем сайте, поддержите пожалуйста мой проект, чтобы о нем узнали другие люди - кликните plizz :) на иконку в соц. сети, чтобы поделиться материалом с другими.