НовостиАдминистрированиеУправления хостингомАрхив
21 июля 2023

Введение в безопасность интерфейса в WordPress: Экранирование элементов

Если вы разработчик для WordPress, который пишет на HTML/CSS/JS (что составляет 100% разработчиков тем и 99% разработчиков плагинов), вам следует знать основы безопасности интерфейса в WordPress. WordPress предоставляет все инструменты, необходимые для того, чтобы сделать тему или плагин безопасными. Вам просто нужно знать, как и когда использовать каждый инструмент.

Например, вашей ответственностью в качестве разработчика интерфейса может быть предотвращение, чтобы неэкранированный контент отображался на странице.

Безопасность этоваша ответственность

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

Если хакер уже может изменить код/базу данных/контент, какая разница, насколько безопасен мой код интерфейса? Неужели он не мог уже нанести больший вред?

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

Но даже в таком случае, вы все равно несете ответственность за то, чтобы сделать код интерфейса безопасным. Вот несколько причин, почему:

  • Хорошая безопасность интерфейса предотвращает возможность возникновения крупных ошибок из-за неправильного действия пользователя. Если пользователь случайно введет специальный символ в поле, где его быть не должно, страница не взорвется .
    • Некоторые атаки ограничены. Возможно, у хакера был минимальный контроль, и он мог изменить только определенный кусок контента в базе данных. Вы можете предотвратить превращение целенаправленной атаки в более обширную.
    • Безопасность это луковица. Наиболее важный (обычно несъедобный) слой это отображение интерфейса. Хорошая защита делает его немного прочнее, мешая хакерам использовать страницу.

Достаточно напутствий. Давайте поговорим об обеспечении безопасности тем и плагинов WordPress.

О чем мы беспокоимся?

Основная забота разработчика интерфейса это предотвращение межсайтового скриптинга (сокращенно XSS).

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

Что значит экранирование?

В компьютерной терминологии слово экранировать имеет особое значение:

Конвертировать символ или строку символов таким образом, чтобы они воспринимались буквально в пределах определенного контекста, обычно для предотвращения того, чтобы эти символы интерпретировались как код.

Другими словами, в контексте разработки интерфейса WordPress: Экранирование превращает возможно плохой контент в безопасный контент.

Наибольшую опасность здесь в основном представляют теги и прочие методы выполнения JavaScript (например, onclick=\"javascript:\"). Если может выводить и исполняться на странице, это очень опасно. Экранирование означает превращение его в <script>, что более безопасно.

Почему следует использовать экранирование:

Если вы незнакомы с XSS, небольшой пример покажет вам, в чем риск.

Предположим, в вашей теме есть поле для добавления ссылки читать далее . На панели инструментов WordPress это будет выглядеть следующим образом:

1.png

Вы бы хотели, чтобы в вашей теме эта ссылка отображалась внизу поста, таким образом:

2.png

Поэтому, вы открываете single.php (файл, ответственный за отображение постов в блоге) и добавляете следующее внизу:

<?php
$read_more_link = get_post_meta(
    get_the_ID(), 
    'read_more_link', 
    true
);
?>
<!-- Don't do this -->
<a href=\"<?php echo $read_more_link; ?>\">Read More</a>

Предположим, кто-то незаконно получает доступ и вводит в ваше поле следующий текст:

3.png

Когда вы заходите на страницу, вы видите следующее:

4.png

Ой! Если плохой ввод позволит плохому человеку запустить JavaScript, он сможет:

  • Перенаправить пользователя;
    • Похитить куки пользователя;
    • Сделать еще что-то плохое.

Экранирование всего

Теперь, когда мы знаем, насколько важным является экранирование, давайте рассмотрим способы экранирования, предоставленные в WordPress, и дадим определение каждому из них.

Функция: esc_html

Используется для: Вывод, в котором не должно быть абсолютно никакого HTML.

Что он делает: Конвертирует специальные символы HTML (такие как , &) в их экранированные варианты (&lt;, &gt;, &amp;).

На примере в теме будут отображаться только текстовые поля:

<?php
$dog_name = get_post_meta($post_id, 'dog_name', true);
?>
<span class=\"dog-name\"><?php
echo esc_html($dog_name);
?></span>

Функция: esc_attr

Используется для: Вывод используется в контексте HTML-атрибута (\"title\", \"data-\" поля, \"alt\" текст).

Что он делает: То же самое, что и esc_html. Единственное отличие к каждой функции применяются разные фильтры WordPress.

Здесь esc_attr используется для изображения:

<img src=\"/images/duck.png\" 
alt=\"<?php echo esc_attr($alt_text); ?>\" 
title=\"<?php echo esc_attr($title); ?>\">

Функция: esc_url

Используется для: Вывод обязательно является URL. Примерами могут быть src-атрибуты и href-значения изображений.

Что он делает: Более тщательное и специфичное экранирование, по сравнению с функциями esc_attr и esc_html , которое устраняет или конвертирует любые символы, запрещенные в URL, в безопасный для URL формат.

Функцию esc_url следует использовать, когда вам нужно отобразить ссылку или динамический путь к изображению:

<a href=\"<?php echo esc_url($url); ?>\">Текст ссылки</a>
<img src=\"<?php echo esc_url($image_url); ?>\" >

Функция: esc_js

Используется для: Отображение строк JavaScript, преимущественно встроенных с помощью атрибутов, вроде onclick.

Что он делает: Конвертирует специальные символы вроде , кавычки все, что может разбить код JavaScript.

esc\js это, наверное, наименее используемая функция esc\, и на это есть несколько причин:

  1. Большая часть JS загружается в отдельный файл.
    1. Большая часть JS не написана встроенным образом в качестве атрибутов.
    2. Для невстроенного JS json_encode это лучший вариант.

Но, если вам когда-либо потребуется экранировать встроенный JS, это нужно делать следующим образом:

<?php
$message = get_post_meta(
    get_the_ID(),
    'onclick_message',
    true );
?>
<a href=\"/blog/\" onclick=\"alert('<?php echo esc_js( $message ); ?>')\">...</a>

Функция: json_encode

Используется для: Отображение переменной PHP для использования в JavaScript.

Что он делает: Конвертирует переменную PHP (объект, строку, массив данных, и пр.) в чувствительную экранированную JavaScript-версию этой переменной PHP.

В частности, эта функция полезна для блоков , в которых используются переменные WP. Простой пример:

<?php
$categories = get_categories();
?>
<script type=\"text/javascript\">
    var allCategories = <?php
    echo json_encode(
        $categories
    );
?>;
// Здесь нужно сделать с категориями что-то интересное
</script>

Функция: wp_kses

Используется для: Вывод, который должен допускать некоторое количество HTML, но не все теги или атрибуты.

Что он делает: Разбивает контент любых тегов или атрибутов, которые не отвечают списку правил допуска.

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

В базовом примере будут отображаться комментарии:

<div class=\"comment-text\">
<?php
echo wp_kses(
    $comment_text,
    // Допускаются только теги <a>, <strong>, и <em>
    array(
        'a' => array(
            // Здесь мы допускаем атрибуты 'href' и 'title' – больше ничего не допускается!
            'href' => array(),
            'title' => array()
         ),
        'br' => array(),
        'em' => array(),
        'strong' => array()
    )
);
?>
</div>

Что представляют собой версии функций экранирования e и x (escattre,escattrx)?

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

Если вы разрабатываете тему или плагин для широкого распространения (а не для одноразового проекта клиента), вам наверняка захочется сделать каждую строку многоязычной. Это означает наличие PHP-строк, которые ранее были под вашим контролем, а теперь могут изменяться переводчиками но при этом, их все равно нужно экранировать (никому нельзя доверять):

<a href=\"/blog/\" title=\"<?php esc_attr_e('Go To Blog', 'my_theme'); ?>\">Blog</a>

Второй параметр функций _e это домен перевода. Он используется переводчиками, когда они пишут и генерируют переводы.

Функции _x (вроде esc_html_x) это, в принципе, то же самое, что и _e, с добавленным аргументом контекст , объясняющим контекст используемого слова или фразы. Могут использоваться для слов с несколькими значениями:

<!-- Здесь мы просим пользователя откомментировать (глагол): -->
<a href=\"#comment\">
<?php
echo esc_html_x(
    'Comment', 'Verb: To leave a comment',
    // Это помощь по контексту
    'my_theme');
?>
</a>
<!-- Здесь мы просто добавляем заголовок с текстом \"Комментарий\" -->
<h3>
<?php
echo esc_html_x(
    'Comment', 'Noun: An individual comment',
    // Это помощь по контексту
    'my_theme'
);
?>
</h3>

Что такое thetitle и thecontent?

Если вы взломаете стандартную тему WordPress (которая в момент написания этой статьи называлась Twenty Fifteen ), вы увидите следующий код, отображающий название поста:

<header class=\"entry-header\">
<?php
the_title('<h1 class=\"entry-title\">',
    '</h1>' );
?>
</header>
<!-- .entry-header -->

Вы также увидите неэкранированный призыв к the_content, который выглядит следующим образом:

<?php the_content(); ?>

Вы можете запаниковать. Почему эти функции не экранированы?! На это есть 2 причины:

1. WordPress автоматически их экранирует

Функции вроде the_title созданы для удобства это инструменты, которые упрощают разработку интерфейса. То есть, чтобы сделать все еще проще для разработчиков, WordPress сам автоматически экранирует вывод для the_title.

2. Контекст: Некоторый контент это HTML

В случае с the_content, ожидается, что вывод будет неэкранированным HTML. Когда пользователь добавляет к контенту, мы можем предположить, что ему на самом деле нужен на странице, а не его экранированная версия.

Если вы беспокоитесь о безопасности с точки зрения того, что пользователь будет иметь возможность добавлять скрипты к выводу the_content, вы можете использовать wp_kses для разбивки нежелательных тегов в окончательном результате. Это подходит для субдоменов и совместных хостингов, и, скорей всего, именно это используется на WordPress.com (хостинговой версии WordPress, где пользователям не разрешается добавлять собственный JavaScript).

Полезный совет: Если вы хотите использовать the_title в качестве атрибута HTML, используйте the_title_attibute чтобы обезопасить экранирование. the_title_attribute в действии:

<span title=\"<?php the_title_attribute(); ?>\">...</span>