Я использую очиститель HTML для очистки пользовательского ввода. У меня настроен список разрешенных элементов, что означает, что любой тег, отсутствующий в списке разрешенных, удаляется. Код ниже:
require_once "HTMLPurifier.standalone.php";
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.AllowedElements', array('strong','b','em','i'));
$purifier = new HTMLPurifier($config);
$safe_html = $purifier->purify($dirty_html));
Вместо того, чтобы только сохранять их содержимое, я хотел бы, чтобы элементы, которые не включены в список, были экранированы и отправлены обратно в виде текста.
Для иллюстрации приведем белый список, показанный выше, следующую входную строку:
<a href="javascript:alert('XSS')"><strong>CLAIM YOUR PRIZE</strong></a>
превращается в "<strong>CLAIM YOUR PRIZE</strong>"
, так как a
не входит в белый список Так же,
<b>Check the article <a href="http://example.com/">here</a></b>
становится "<b>Check the article here</b>"
,
Есть ли способ превратить два приведенных выше примера в следующее:
<a href="javascript:alert('XSS')"><strong>CLAIM YOUR PRIZE</strong></a>
<b>Check the article <a href="http://example.com/">here</a></b>
исключительно путем настройки конфигурации очистителя HTML не прибегая к регулярным выражениям «хаки»? Если есть, то я хотел бы знать, как это делается.
Настройки Core.EscapeInvalidTags
должно быть то, что вы ищете:
require_once(__DIR__ . '/library/HTMLPurifier.auto.php');
$dirty_html = '<a href="javascript:alert(\'XSS\')"><strong>CLAIM YOUR PRIZE<div></div></strong></a>';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.AllowedElements', array('strong','b','em','i'));
$config->set('Core.EscapeInvalidTags', true);
$purifier = new HTMLPurifier($config);
$safe_html = $purifier->purify($dirty_html);
echo $safe_html . PHP_EOL;
…дает:
<a href="javascript:alert('XSS')"><strong>CLAIM YOUR PRIZE<div /></strong></a>
Я бросил в недопустимый дочерний элемент <div></div>
так что вы можете увидеть, что происходит: очиститель HTML все равно «изменит» исходный HTML из-за его анализа (<div></div>
становится <div />
), но информация остается (и преобразуется в <div />
).
Других решений пока нет …