Является ли strip_tags () уязвимым для атак сценариев? - PullRequest
48 голосов
/ 26 апреля 2011

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

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

echo $content;

?

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

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

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

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

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

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

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

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

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

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

Ответы [ 4 ]

48 голосов
/ 26 апреля 2011

Как следует из названия, 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 счетчик с именем depth увеличивается, а символигнорируется.

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

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

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

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

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

Убедитесь, что тег HTML не существуетв возвращаемой строке.

10 голосов
/ 26 апреля 2011

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

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

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

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

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

, поскольку можно легко завершить кавычку с помощью " и вставить обработчик сценария.

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

3 голосов
/ 02 ноября 2017

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

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

В строке «настоящие» теги - это <a> и </a>, поскольку только < и script> не являются тегами.

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

2 голосов
/ 26 апреля 2011

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

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

...