Уязвимы ли теги полосы() для атак сценариев?


Существует ли известная XSS или другая атака, которая проходит мимо

$content = "some HTML code";
$content = strip_tags($content);

echo $content;

?

В руководстве есть предупреждение:

Эта функция не изменяет никаких атрибутов тегов, которые вы разрешаете использовать с помощью allowable_tags, включая атрибуты стиля и onmouseover, которыми может злоупотреблять злонамеренный пользователь при публикации текста, который будет показан другим пользователям.

Но это связано только с использованием параметра allowable_tags.

Без разрешенных набор тегов, является ли strip_tags() уязвимым для любой атаки?

Крис Шифлетт, кажется, говорит, что это безопасно:

Используйте Зрелые решения

По возможности используйте зрелые, существующие решения вместо того, чтобы пытаться создавать свои собственные. Такие функции, как strip_tags() и htmlentities(), являются хорошим выбором.

Правильно ли это? Пожалуйста, если возможно, приведите источники.

Я знаю о очистителе HTML, htmlspecialchars() и т. Д.- Я не ищу лучшее метод очистки HTML. Я просто хочу знать об этой конкретной проблеме. Это теоретический вопрос, который возник здесь.

Ссылка: strip_tags() реализация в исходном коде PHP

Author: Community, 2011-04-26

4 answers

Как следует из названия, strip_tags следует удалить все HTML-теги. Единственный способ доказать это - проанализировать исходный код. Следующий анализ применяется к вызову strip_tags('...') без второго аргумента для тегов из белого списка.

Во-первых, немного теории о тегах HTML: тег начинается с <, за которым следуют символы, не содержащие пробелов. Если эта строка начинается с ?, ее не следует анализировать . Если эта строка начинается с !--, она считается комментарием и следующий текст также не следует анализировать. Комментарий завершается символом -->, внутри такого комментария допускаются такие символы, как < и >. Атрибуты могут встречаться в тегах, их значения могут быть необязательно заключены в кавычки (' или "). Если такая цитата существует, она должна быть закрыта, в противном случае, если встречается >, тег не закрывается.

Код <a href="example>xxx</a><a href="second">text</a> интерпретируется в Firefox как:

<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>

Функция PHP strip_tags упоминается в строка 4036 из ext/standard/string.c. Эта функция вызывает внутреннюю функцию php_strip_tags_ex.

Существуют два буфера, один для вывода, другой для "внутренних HTML-тегов". Счетчик с именем depth содержит количество открытых угловых скобок (<).
Переменная in_q содержит символ кавычки (' или "), если таковой имеется, и 0 в противном случае. Последний символ сохраняется в переменной lc.

Функции содержат пять состояний, три из которых упомянутая в описании выше функция. На основе этой информации и тела функции могут быть получены следующие состояния:

  • Состояние 0 - это состояние вывода (не в каком-либо теге)
  • Состояние 1 означает, что мы находимся внутри обычного html-тега (буфер тегов содержит <)
  • Состояние 2 означает, что мы находимся внутри тега php
  • Состояние 3: мы вышли из состояния вывода и столкнулись с символами < и ! (буфер тегов содержит <!)
  • Состояние 4: внутренний HTML-комментарий

Нам просто нужно быть осторожными, чтобы ни один тег не мог быть вставлен. То есть <, за которым следует символ, не содержащий пробелов. Строка 4326 проверяет случай с символом <, который описан ниже:

  • Если внутри кавычек (например, <a href="inside quotes">), символ < игнорируется (удаляется из вывода).
  • Если следующий символ является пробелом, < добавляется в выходной буфер.
  • если вне HTML-тега, состояние становится 1 ("внутренний HTML-тег"), а последнему символу lc присваивается значение <
  • В противном случае, если внутри HTML-тега a счетчик с именем depth увеличивается, а символ игнорируется.

Если > выполняется, когда тег открыт (state == 1), in_q становится 0 ("не в кавычке") и state становится 0 ("не в теге"). Буфер тегов отбрасывается.

Проверка атрибутов (для таких символов, как ' и ") выполняется в буфере тегов, который отбрасывается. Итак, вывод таков:

Strip_tags без белого списка тегов безопасен для включения вне тегов, ни один тег не будет разрешен.

Под "внешними тегами" я подразумеваю не в тегах, как в <a href="in tag">outside tag</a>. Текст может содержать < и >, хотя, как и в >< a>>. Однако результат не является допустимым HTML, <, > и & все еще нужно бежать, особенно &. Это можно сделать с помощью htmlspecialchars().

Описание для strip_tags без белого списка аргумент был бы следующим:

Гарантирует, что в возвращаемой строке не существует HTML-тега.

 45
Author: Lekensteyn, 2011-04-29 19:42:25

Я не могу предсказать будущие эксплойты, тем более, что я не смотрел исходный код PHP для этого. Однако в прошлом были эксплойты из-за того, что браузеры принимали, казалось бы, недопустимые теги (например, <s\0cript>). Так что вполне возможно, что в будущем кто-то сможет использовать странное поведение браузера.

Кроме того, отправка вывода непосредственно в браузер в виде полного блока HTML никогда не должна быть небезопасной:

echo '<div>'.strip_tags($foo).'</div>'

Однако это не так безопасно:

echo '<input value="'.strip_tags($foo).'" />';

Потому что можно легко закончить цитату через " и вставить обработчик скрипта.

Я думаю, что гораздо безопаснее всегда преобразовывать случайные < в &lt; (и то же самое с кавычками).

 10
Author: Matthew, 2011-04-26 16:54:11

Теги полосы совершенно безопасны - если все, что вы делаете, это вывод текста в тело html.

Не обязательно безопасно помещать его в атрибуты mysql или URL.

 2
Author: kemus, 2011-04-26 10:08:48

Согласно этому онлайн-инструменту , эта строка будет "идеально" экранирована, но в результате получится еще одна вредоносная!

<<a>script>alert('ciao');<</a>/script>

В строке "реальными" тегами являются <a> и </a>, поскольку < и script> сами по себе не являются тегами.

Я надеюсь, что я ошибаюсь или что это просто из-за старой версии PHP, но лучше проверить в вашей среде.

 2
Author: Ludovico Grossi, 2017-11-02 20:53:19