Как следует из его названия, strip_tags
должен удалить все теги HTML. Единственный способ доказать это - проанализировать исходный код. Следующий анализ относится к вызову strip_tags('...')
, без второго аргумента для белых списков.
Прежде всего, некоторая теория о тегах HTML: тег начинается с <
, за которым следуют символы без пробелов. Если эта строка начинается с ?
, это should not be parsed. Если эта строка начинается с !--
, это считается комментарием, и следующий текст не должен анализироваться. Комментарий заканчивается -->
, внутри такого комментария допускаются символы, такие как <
и >
. Атрибуты могут встречаться в тегах, их значения могут быть дополнительно окружены символом кавычки ('
или "
). Если такая цитата существует, она должна быть закрыта, иначе, если встречается >
, тег не закрывается.
Код <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
упоминается в line 4036 of ext/standard/string.c. Эта функция вызывает internal function php_strip_tags_ex.
Существуют два буфера, один для вывода, другой для «внутри HTML-тегов». Счетчик с именем depth
содержит количество угловых скобок (<
).
Переменная in_q
содержит символ цитаты ('
или "
), если таковой имеется, и 0
в противном случае. Последний символ хранится в переменной lc
.
Функции содержат пять состояний, три упомянутые в описании выше функции. На основе этой информации и функции тела, следующие состояния могут быть получены:
- Состояние 0 является состояние выхода (не в любом теге)
- Государство 1 означает, что мы находимся внутри нормального HTML тег (тег буфер содержит
<
)
- государство 2 означает, что мы внутри PHP тега
- State 3: мы пришли из выходного состояния и столкнулись с
<
и !
символы (буфер тег содержит <!
)
- государства 4: внутри HTML комментарий
Нам нужно просто быть осторожным, чтобы ни один тег не был вставлен. То есть, <
, за которым следует символ без пробелов. Line 4326 проверяет дела о <
с характером, который описан ниже:
- Если внутри котировки (например
<a href="inside quotes">
), то <
символ игнорируется (удаляется из выходного сигнала).
- Если следующий символ является символом пробела, в выходной буфер добавляется
<
.
- если вне HTML тега, состояние становится
1
(«внутри HTML-тега») и последний символ lc
установлен в <
- В противном случае, если внутри в HTML-тег, счетчик с именем
depth
увеличивается и характер игнорируются.
Если >
выполняется в то время как тег открыт (state == 1
) in_q
становится 0
(«не в цитате») и state
становится 0
(«не в теге»). Буфер тега отбрасывается.
Проверка атрибутов (для таких символов, как '
и "
) выполняется в буфере тега, который отбрасывается. Таким образом, вывод:
strip_tags без ярлыка тега безопасен для включения внешних тегов, без тегов.
Под «наружными тегами», я имею в виду не в тегах, как в <a href="in tag">outside tag</a>
. Текст может содержать <
и >
, хотя, как и в >< a>>
. Результат недействителен HTML, хотя <
, >
и &
еще нужно избежать, особенно &
. Это можно сделать с помощью htmlspecialchars()
.
Описание для strip_tags
без белого списка аргументов будет:
Гарантирует, что ни один HTML тег не существует в возвращаемой строке.
Ну, никаких аргументов, он не выдает _all_ теги, поэтому я не вижу, как может быть какой-либо эксплойт. Самое худшее, что произойдет, - это кто-то, кто кормит вас недействительной разметкой (без закрывающих тегов), но этот худший случай просто означает, что 'strip_tags' выделяет намного больше текста. – Damon
@ Gordon благодарит меня, но я имею в виду целый кусок данных HTML, поэтому никаких инъецированных имен файлов и т. Д. (Что, если я правильно понимаю, это то, что обсуждается в форуме). Насколько я понимаю, поток Не доказывайте уязвимость в strip_tags(), но продолжайте рекомендовать htmlspecialchars() - это то, что я обычно делаю, но я хочу знать, действительно ли это необходимо * –
Вы можете проверить способ работы 'strip_tags' глядя на [реализацию] (http://lxr.php.net/opengrok/xref/PHP_5_3/ext/standard/string.c#php_strip_tags_ex). – Lekensteyn