Вопрос или проблема
У меня есть кастомная тема. Я хочу вывести заголовок моего поста. Я уже достиг этого, используя <h1><?php the_title();?></h1>
. Однако некоторые говорят, что это не экранировано. Действительно, я могу запустить JS, например <script>alert("test");</script>
, если помещу это в заголовок поста. Я пробовал (1) <?php esc_html(the_title('<h1>','</h1>'))?>
, но это также запускает вышеупомянутый JS и не выводит никакой HTML. Также пробовал (2) <h1><?php echo esc_html(the_title);</h1>
с тем же результатом, что и (1).
С Новым Годом! /dfr
Вы использовали бы это так:
<?php the_title(); ?>
Действительно, я могу запустить JS, например alert(“test”), если помещу это в заголовок поста.
Это потому, что вы либо супер администратор в мультисайте, либо администратор на не-мультисайте, эти получают возможность unfiltered_html
обходить всю очистку при сохранении. Поэтому вы можете вставлять сырые теги скриптов в посты, другие пользователи не могут, и эта возможность отключена на многих корпоративных хостингах, так как она представляет угрозу безопасности.
Сказав это, это не имеет отношения к экранированию, ваш заголовок может содержать теги скрипта, и экранирование все равно будет их печатать, но теги будут экранированы и видны людям, читающим их на фронтенде, а не выполняться/восприниматься как реальные теги.
Так что вместо этого:
- Используйте
the_title()
как есть, чтобы напрямую вывести заголовок - Или, если вы обеспокоены тем, что у пользователя есть возможность
unfiltered_html
, используйтеecho esc_html( get_the_title(
Однако обратите внимание, что заголовок используется во многих других местах, таких как OEmbed и SEO теги, а также теги заголовка, и может быть легче удалить возможность unfiltered_html
, и я рекомендую вам сделать это, хотя бы в качестве меры безопасности.
Я пробовал (1)
<?php esc_html(the_title('<h1>','</h1>'))?>
Это не сработало по нескольким причинам, которые не имеют отношения к WordPress, но подчеркивают отсутствующие знания о базах PHP
- Нет
echo
! Поэтому даже если бы это сработало, оно бы ничего не напечатало the_title
по умолчанию не возвращает значение, оно выводит напрямую
Это означает, что код эквивалентен этому:
echo esc_html('');
the_title('<h1>','</h1>');
Также пробовал (2)
<h1><?php echo esc_html(the_title);</h1>
с тем же результатом
Это лучше, так как включает echo
, но вы попросили экранировать саму функцию, а не заголовок поста, это почти эквивалентно этому:
echo esc_html( function the_title() { .... } );
Что, вероятно, приведет к предупреждению PHP типа:
Warning: Uncaught Error: Object of class Closure could not be converted to string in...
Важные моменты, которые следует учесть на будущее:
- Сначала проверьте, но общее правило заключается в том, что
the_...
будет выводить напрямую безecho
, аget_the
илиget_
требуют оператораecho
и функции экранирования. - Функции, начинающиеся с
the_
, как правило, выполняют собственное экранирование внутри - Не делайте двойное экранирование!
esc_html( esc_html(
это очень плохо и может позволить вещам пройти, если они правильно сконструированы - вызов функции включает
()
где-то, вы не можете применить экранирование как модификатор или буфер, вызываяescape(function_name)
- экранируйте как можно позже, желательно в момент вывода
- избегайте сбора HTML-фрагментов в переменную, а затем вывода их в конце, это делает очень трудным правильное экранирование вещей
- не экранируйте ввод, для этого предназначены очистка и валидация, экранирование предназначено только для вывода
- Не пытайтесь использовать
esc_js
иesc_sql
, они не делают то, что, кажется, делают, и имеют очень специфические внутренние применения.wpdb->prepare
должен покрыть всю SQL-связанную экранирование, аwp_json_encode
может подготавливать данные для JavaScript, так что вам не нужно конструировать их из строк при показе страницы
Ответ или решение
Выбор оптимальной практики для экранирования функции the_title()
в WordPress имеет важное значение для обеспечения безопасности и корректности отображения заголовков на вашем сайте. Давайте разберем детали этого процесса с учетом того, как работает the_title()
, и возможных ошибок, которые вы можете столкнуться при его использовании.
Проблема и контекст
Вы используете пользовательскую тему и выводите заголовок поста с помощью кода <h1><?php the_title(); ?></h1>
. Однако, как вы заметили, это не экранированный вывод, и если у пользователя есть привилегия unfiltered_html
, это может привести к выполнению небезопасного кода, такого как <script>alert("test");</script>
.
Почему ваше текущее решение не работает
-
Ошибка в экранировании:
- Вы использовали
esc_html(the_title('<h1>','</h1>'))
, что неверно, так какthe_title()
по умолчанию выводит данные напрямую и не возвращает значение. В данном случае вы экранировали пустую строку.
- Вы использовали
-
Отсутствие вывода:
- В версии
<h1><?php echo esc_html(the_title);</h1>
функцияthe_title
была передана как объект, что приводит к PHP ошибке, когда система пытается экранировать саму функцию, а не её вывод.
- В версии
Правильное решение
Чтобы корректно экранировать заголовок поста и избежать потенциальных проблем безопасности, следуйте этому подходу:
<h1><?php echo esc_html( get_the_title() ); ?></h1>
-
Используйте
get_the_title()
:- Эта функция возвращает строку, которая является заголовком поста, без непосредственного вывода её на экране.
-
Экранирование с помощью
esc_html()
:- Примените
esc_html()
к строке, полученной отget_the_title()
, чтобы обеспечить безопасный вывод, экранировав все HTML теги и возможный опасный код.
- Примените
Рекомендации по безопасности и производительности
-
Избегайте привилегий
unfiltered_html
:- Если это возможно, удалите эту привилегию у пользователей. Это улучшит безопасность вашего сайта.
-
Экранирование на этапе вывода:
- Всегда старайтесь экранировать данные непосредственно перед их выводом. Это позволит предотвратить внедрение вредоносного кода в HTML.
-
Понимание WordPress функций:
- Функции, начинающиеся с
get_
, как правило, возвращают значение, которое вы должны выводить вручную, в то время какthe_
обычно выводят данные сразу.
- Функции, начинающиеся с
Заключение
Чтобы обеспечить безопасность вашего сайта, всегда экранируйте пользовательский ввод на этапе вывода с помощью esc_html()
и правильно выбирайте подходящие функции WordPress (the_title()
vs. get_the_title()
). Это создаст более безопасную среду для вашего сайта и улучшит качество кода.