Совет по безопасности: Безопасна ли функция strip_tags()

Источник: «Security Tip: Is `strip_tags()` Secure?»
PHP включает несколько очень удобных функций, ориентированных на безопасность, но вы должны знать, как правильно их использовать, иначе рискуете оставить значительную уязвимость, ожидающую своего применения!

Часто можно встретить старые приложения PHP, использующие некоторые встроенные функции безопасности, такие как strip_tags(), htmlspecialchars() и htmlentities(). Каждая из них работает по-разному, но достаточно ли они безопасны для использования? И когда следует использовать каждую из них?

Давайте рассмотрим strip_tags() и, надеюсь, ответим на этот вопрос!

Согласно документации PHP:

Функция пытается возвратить строку, из которой удалены все NULL-байты, HTML- и PHP-теги из заданной строки (string). Для удаления тегов используется тот же механизм, что и в функции fgetss().

Сама функция имеет два параметра, первый из которых является обязательным и представляет собой строковое значение, подлежащее очистке, а второй — необязательный список разрешённых HTML-тегов.

strip_tags(string $string, array|string|null $allowed_tags = null): string

Но так ли это безопасно?

Давайте ответим на этот вопрос с помощью нескольких примеров…

return strip_tags("Hello <b>World</b>!")

// Hello World!

✅ Пока все хорошо, она делает то, что заявлено — удаляет HTML-теги из строк!

return strip_tags("Hello <img src=x onerror=\"alert('Boom!')\"> World!");

// Hello World!

✅ Как и следовало ожидать, она удаляет и сложные теги.

$string = "Hello <img src=x onerror=\"alert('Boom!')\"> World!";

return strip_tags($string, "<img>");

// Hello <img src=x onerror="alert('Boom!')"> World!

❌ К сожалению, она слепо разрешает весь тег, который включает в себя любую полезную нагрузку XSS. Вы не можете использовать strip_tags() с пользовательским вводом, когда хотите разрешить некоторые теги. Вместо этого вам нужен полнофункциональный HTML Purifier.

$value = strip_tags("' onload=\"alert('Boom!')\" '");

return "<input type='text' name='comments' value='{$value}'>";

// <input type='text' name='comments' value='' onload="alert('Boom!')" ''>

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

Резюме

Функцию strip_tags() можно безопасно использовать, когда вы удаляете только HTML-теги из содержимого, выводимого прямо на страницу, без каких-либо атрибутов или сложных HTML структур.

Не используйте её, если вам нужно разрешить определённые теги (используйте HTML Purifier вместо неё), и не используйте её внутри атрибутов или сложных структур.

Дополнительные материалы

Предыдущая Статья

Основы TypeScript: Создание типов, перечислений и интерфейсов

Следующая Статья

Основы TypeScript: Объединение, Литеральные и Размеченные типы