Почему важно фильтровать пользовательский ввод в WordPress
Любой контент, вводимый пользователями на сайте — будь то комментарии, отзывы, поля форм или пользовательские метаданные — потенциально опасен. Злоумышленник может вставить вредоносный HTML или JavaScript, что приведёт к XSS-атакам и компрометации сайта или данных посетителей. Поэтому нужно обязательно фильтровать ввод.
Стандартный способ — использовать встроенную функцию WordPress wp_kses_post(), которая пропускает только разрешённые теги и атрибуты, аналогично тому, как WordPress обрабатывает содержимое постов.
Диагностика проблемы: как понять, что ввод не фильтруется
- Пользователи жалуются на появление HTML-тегов как текста на сайте.
- В исходном коде страницы видны подозрительные скрипты или теги.
- В логах сервера или браузера появляются ошибки, связанные с XSS.
- При тестировании можно вставить
<script>alert('XSS')</script>в форму и проверить, выводится ли алерт.
Пошаговое решение: применение wp_kses_post() при выводе
1. Фильтрация данных при выводе
Вместо прямого вывода пользовательского контента используйте:
<?php echo wp_kses_post( $user_input ); ?>Где $user_input — данные, полученные от пользователя.
2. Пример для кастомного поля
$custom_field = get_post_meta( get_the_ID(), 'custom_field_key', true );
echo wp_kses_post( $custom_field );3. Если нужно расширить список разрешённых тегов
Можно использовать wp_kses() с кастомным массивом разрешённых тегов и атрибутов:
$allowed_tags = wp_kses_allowed_html( 'post' );
// Добавим тег <iframe> с атрибутами
$allowed_tags['iframe'] = array(
'src' => true,
'width' => true,
'height' => true,
'frameborder' => true,
'allowfullscreen' => true,
);
$filtered = wp_kses( $user_input, $allowed_tags );
echo $filtered;Проверка результата после внедрения
- Вставьте в форму тестовый скрипт:
<script>alert('XSS')</script>— он должен быть удалён из вывода. - Разрешённые теги, например
<b>или<a href="...">, должны корректно отображаться. - Проверьте исходный код страницы в браузере — вредоносных тегов не должно быть.
Частые ошибки и как их исправить
- Фильтрация на входе вместо на выходе: Некоторые пытаются фильтровать данные сразу при сохранении — это ограничивает гибкость. Лучше фильтровать при выводе.
- Использование
esc_html()вместоwp_kses_post():esc_html()полностью экранирует HTML, что не всегда нужно. Если хотите разрешить безопасный HTML, используйтеwp_kses_post(). - Расширение разрешённых тегов без понимания рисков: Добавляя теги, например
iframe, убедитесь, что источники надёжны, иначе открываете уязвимости.
Практические советы по безопасности и производительности
- Всегда фильтруйте вывод, а не только ввод. Это гарантирует защиту вне зависимости от способа сохранения данных.
- Минимизируйте список разрешённых тегов — чем меньше, тем безопаснее.
- Используйте
wp_kses_post()для большинства случаев, он покрывает стандартные теги постов и комментариев. - Кэшируйте отфильтрованный контент, если он часто выводится без изменений, чтобы снизить нагрузку.
- Регулярно обновляйте WordPress и плагины — иногда улучшения безопасности добавляются в ядро.
Сравнение методов фильтрации пользовательского контента
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| wp_kses_post() | Фильтрация вывода с набором безопасных тегов, как в постах | Баланс безопасности и функционала, встроено в WP | Нельзя кастомизировать без дополнительного кода |
| wp_kses() с кастомным набором | Фильтрация с произвольным набором разрешённых тегов | Гибкость, можно добавить iframe, видео и др. | Риск открытия XSS, требует внимательности |
| esc_html() | Полное экранирование HTML | Максимальная безопасность | Пользовательский HTML полностью не отображается |