Уязвимы ли теги полосы() для атак сценариев?
Существует ли известная XSS или другая атака, которая проходит мимо
$content = "some HTML code";
$content = strip_tags($content);
echo $content;
?
В руководстве есть предупреждение:
Эта функция не изменяет никаких атрибутов тегов, которые вы разрешаете использовать с помощью allowable_tags, включая атрибуты стиля и onmouseover, которыми может злоупотреблять злонамеренный пользователь при публикации текста, который будет показан другим пользователям.
Но это связано только с использованием параметра allowable_tags
.
Без разрешенных набор тегов, является ли strip_tags()
уязвимым для любой атаки?
Крис Шифлетт, кажется, говорит, что это безопасно:
Используйте Зрелые решения
По возможности используйте зрелые, существующие решения вместо того, чтобы пытаться создавать свои собственные. Такие функции, как strip_tags() и htmlentities(), являются хорошим выбором.
Правильно ли это? Пожалуйста, если возможно, приведите источники.
Я знаю о очистителе HTML, htmlspecialchars() и т. Д.- Я не ищу лучшее метод очистки HTML. Я просто хочу знать об этой конкретной проблеме. Это теоретический вопрос, который возник здесь.
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-тега.
Я не могу предсказать будущие эксплойты, тем более, что я не смотрел исходный код PHP для этого. Однако в прошлом были эксплойты из-за того, что браузеры принимали, казалось бы, недопустимые теги (например, <s\0cript>
). Так что вполне возможно, что в будущем кто-то сможет использовать странное поведение браузера.
Кроме того, отправка вывода непосредственно в браузер в виде полного блока HTML никогда не должна быть небезопасной:
echo '<div>'.strip_tags($foo).'</div>'
Однако это не так безопасно:
echo '<input value="'.strip_tags($foo).'" />';
Потому что можно легко закончить цитату через "
и вставить обработчик скрипта.
Я думаю, что гораздо безопаснее всегда преобразовывать случайные <
в <
(и то же самое с кавычками).
Теги полосы совершенно безопасны - если все, что вы делаете, это вывод текста в тело html.
Не обязательно безопасно помещать его в атрибуты mysql или URL.
Согласно этому онлайн-инструменту , эта строка будет "идеально" экранирована, но в результате получится еще одна вредоносная!
<<a>script>alert('ciao');<</a>/script>
В строке "реальными" тегами являются <a>
и </a>
, поскольку <
и script>
сами по себе не являются тегами.
Я надеюсь, что я ошибаюсь или что это просто из-за старой версии PHP, но лучше проверить в вашей среде.