Esc html


В этой статье я расскажу, как обезопасить себя от инъекций нежелательного кода через переводы в WordPress

Иногда мы забываем, что переводчики веб-сайта тоже люди, и не всегда доброжелательные.

Подменяя файл перевода, переводчики могут нарушить работу сайта и украсть персональные данные пользователей.

Проблема

Чтобы разобраться в ситуации, давайте вспомним ответ на вопрос — «Как чаще всего мы вставляем перевод в нашу тему или плагин?»

<?php echo '<p>' . __('Sometext', 'mytheme') . '</p>';

Казалось бы, что может пойти не так? Давайте подумаем.
Достаточно вставить в файл перевода закрывающуюся скобку «>» или <script>alert('hello');</script> и всё… верстка поехала, сайт выдал ошибку. А всё могло быть даже хуже.

Решение

У WordPress есть две замечательные функции, которые позволяют избежать вставки нежелательных символов в текст перевода:

codex.wordpress.org/Function_Reference/esc_html_2
codex.wordpress.org/Function_Reference/esc_html_e

esc_html__


и esc_html_e соответственно.

Отличие лишь в том, что esc_html_e не нужно выводить через «echo».

Во всех местах, где вы используете конструкцию

__('something', 'mytheme')

нужно использовать

esc_html__('something', 'mytheme')

А конструкцию

_e('something', 'mytheme')

заменить на

esc_html_e('something', 'mytheme')

Ещё один момент

Если у нас имеется конструкция с атрибутом вида:

<?php echo '<a href="#" title="' . __('Attribute value', 'mytheme') . '</a>';

То «эскейпить» её нужно функцией esc_attr__()

codex.wordpress.org/Function_Reference/esc_attr_2

Вывод

Правило «Не доверяй никому!» должно быть в основе разработки, и каждый даже самый минимальный момент ввода-вывода данных должен быть учтен при разработке, чтобы избежать печальных последствий. И переводы — не исключение.

И в завершение — Github для чтения

По данной ссылке кратко описана проблема вывода переводов без эскейпов:

github.com/Automattic/_s/issues/231

sohabr.net

Замена

Замена помогает вашей информации отображаться безопасно конечному пользователю. У WordPress есть множество функций помощников для таких задач.


  • esc_html() – Используй эту функцию когда нужно вывести HTML данные как они есть
  • esc_url() – Используй эту функцию когда нужно очистить ссылки от вредоносных данных. Она так же может использоваться для src и href атрибутов у HTML элемента
  • esc_js() — используйте эту функцию, когда вам нужно очистить JavaScript
  • esc_attr() – Используйте эту функцию для вывода чего-угодно в HTML атрибуты

Большинство функции в WordPress заранее чистят выводимые данные, тем самым вам не нужно делать это повторно. Например, вы можете безопасно использовать функцию the_title().

Чистка и перевод

Вместо того, что использовать echo для вывода данных, в WordPress чаще всего используется специальные функции для локализации такие как _e() и __().

Эти функции обертывают функции локализации, дополнительно добавляя безопасность (чистят данные):


esc_html_e( 'Hello World', 'bologer' );  // тоже самое что и   echo esc_html( __( 'Hello World', 'bologer' ) );

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

esc_html__()  esc_html_e()  esc_html_x()  esc_attr__()  esc_attr_e()  esc_attr_x()

bologer.ru

 function receptar_theme_options_array($options = array())   {   //Preparing output   /**   * Theme customizer options array   */   $options = array(100 . 'colors' => array('id' => 'colors', 'type' => 'section', 'create_section' => esc_html_x('Colors', 'Customizer section title.', 'receptar'), 'in_panel' => esc_html_x('Theme', 'Customizer panel title.', 'receptar'), 'in_panel-description' => '<h3>' . esc_html__('Theme Credits', 'receptar') . '</h3><p class="description">' . sprintf(esc_html_x('%1$s is free WordPress theme developed by %2$s. You can obtain other professional WordPress themes at %3$s. Thank you for using this awesome theme!', '1: linked theme name, 2: theme author name, 3: theme author link.', 'receptar'), '<a href="' . esc_url(wp_get_theme()->get('ThemeURI')) . '" target="_blank"><strong>' .  

c_html(wp_get_theme()->get('Name')) . '</strong></a>', esc_html(wp_get_theme()->get('Author')), '<strong><a href="' . esc_url(wp_get_theme()->get('AuthorURI')) . '" target="_blank">' . esc_html(wp_get_theme()->get('AuthorURI')) . '</a></strong>') . '</p>' . '<p><a href="' . esc_url(wp_get_theme()->get('ThemeURI')) . '#donate" class="donation-link" target="_blank">' . esc_html__('Donate', 'receptar') . '</a></p>'), 100 . 'colors' . 100 => array('type' => 'theme-customizer-html', 'content' => '<h3>' . esc_html__('Accent color', 'receptar') . '</h3>'), 100 . 'colors' . 110 => array('type' => 'color', 'id' => 'color' . '-accent', 'label' => esc_html__('Accent color', 'receptar'), 'description' => esc_html__('This color affects links, buttons and other elements of the website', 'receptar'), 'default' => '#e53739'), 100 . 'colors' . 120 => array('type' => 'color', 'id' => 'color' . '-accent-text', 'label' => esc_html__('Accent text color', 'receptar'), 'description' => esc_html__('Color of text over accent color background', 'receptar'), 'default' => '#ffffff'), 100 . 'colors' . 200 => array('type' => 'theme-customizer-html', 'content' => '<h3>' . esc_html__('Header', 'receptar') . '</h3>'), 100 . 'colors' . 210 => array('type' => 'color', 'id' => 'color' .

header-background', 'label' => esc_html__('Background color', 'receptar'), 'default' => '#2a2c2e'), 100 . 'colors' . 220 => array('type' => 'color', 'id' => 'color' . '-header-text', 'label' => esc_html__('Text color', 'receptar'), 'default' => '#ffffff'), 100 . 'colors' . 300 => array('type' => 'theme-customizer-html', 'content' => '<h3>' . esc_html__('Sidebar', 'receptar') . '</h3>'), 100 . 'colors' . 310 => array('type' => 'color', 'id' => 'color' . '-sidebar-background', 'label' => esc_html__('Background color', 'receptar'), 'default' => '#1a1c1e'), 100 . 'colors' . 320 => array('type' => 'color', 'id' => 'color' . '-sidebar-text', 'label' => esc_html__('Text color', 'receptar'), 'default' => '#9a9c9e'), 100 . 'colors' . 330 => array('type' => 'color', 'id' => 'color' . '-sidebar-headings', 'label' => esc_html__('Headings color', 'receptar'), 'default' => '#ffffff'), 100 . 'colors' . 340 => array('type' => 'color', 'id' => 'color' . '-sidebar-border', 'label' => esc_html__('Borders color', 'receptar'), 'default' => '#3a3c3e'), 100 . 'colors' . 400 => array('type' => 'theme-customizer-html', 'content' => '<h3>' . esc_html__('Content', 'receptar') . '</h3>'), 100 . 'colors' . 410 => array('type' => 'color', 'id' => 'color' . '-content-background', 'label' => esc_html__('Background color', 'receptar'), 'default' => '#ffffff'), 100 .

olors' . 420 => array('type' => 'color', 'id' => 'color' . '-content-text', 'label' => esc_html__('Text color', 'receptar'), 'default' => '#6a6c6e'), 100 . 'colors' . 430 => array('type' => 'color', 'id' => 'color' . '-content-headings', 'label' => esc_html__('Headings color', 'receptar'), 'default' => '#1a1c1e'), 100 . 'colors' . 440 => array('type' => 'color', 'id' => 'color' . '-content-border', 'label' => esc_html__('Borders color', 'receptar'), 'default' => '#eaecee'), 100 . 'colors' . 450 => array('type' => 'theme-customizer-html', 'content' => '<h4>' . esc_html__('Alternative colors', 'receptar') . '</h4>'), 100 . 'colors' . 460 => array('type' => 'color', 'id' => 'color' . '-content-alt-background', 'label' => esc_html__('Background color', 'receptar'), 'default' => '#2a2c2e'), 100 . 'colors' . 470 => array('type' => 'color', 'id' => 'color' . '-content-alt-text', 'label' => esc_html__('Text color', 'receptar'), 'default' => '#9a9c9e'), 100 . 'colors' . 480 => array('type' => 'color', 'id' => 'color' . '-content-alt-headings', 'label' => esc_html__('Headings color', 'receptar'), 'default' => '#ffffff'), 100 . 'colors' . 490 => array('type' => 'color', 'id' => 'color' . '-content-alt-border', 'label' => esc_html__('Borders color', 'receptar'), 'default' => '#3a3c3e'), 100 . 'colors' . 800 => array('type' => 'theme-customizer-html', 'content' => '<h3>' .

c_html__('Footer', 'receptar') . '</h3>'), 100 . 'colors' . 810 => array('type' => 'color', 'id' => 'color' . '-footer-background', 'label' => esc_html__('Background color', 'receptar'), 'default' => '#f5f7f9'), 100 . 'colors' . 820 => array('type' => 'color', 'id' => 'color' . '-footer-text', 'label' => esc_html__('Text color', 'receptar'), 'default' => '#9a9c9e'), 200 . 'fonts' => array('id' => 'fonts', 'type' => 'section', 'create_section' => esc_html_x('Fonts', 'Customizer section title.', 'receptar'), 'in_panel' => esc_html_x('Theme', 'Customizer panel title.', 'receptar')), 200 . 'fonts' . 100 => array('type' => 'theme-customizer-html', 'content' => '<p class="description">' . sprintf(esc_html_x('This theme does not restrict you to a predefined set of fonts. Please use any font service (such as %s) plugin you want and set the plugin according to the information below.', '%s is replaced with linked examples of web fonts libraries such as Google Fonts or Adobe Typekit.', 'receptar'), '<a href="http://www.google.com/fonts" target="_blank"><strong>Google Fonts</strong></a>, <a href="https://typekit.com/fonts" target="_blank"><strong>Adobe Typekit</strong></a>') . '</p>' . '<p>' . esc_html__('List of CSS selectors for predefined theme font sets:', 'receptar') .

lt;/p>' . '<ol>' . '<li><strong>' . esc_html_x('Texts:', 'CSS selector group name.', 'receptar') . '</strong><br />' . '<code>html</code>' . '</li>' . '<li><strong>' . esc_html_x('Headings:', 'CSS selector group name.', 'receptar') . '</strong><br />' . '<code>h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6, .entry-category, .entry-title .entry-edit</code>' . '</li>' . '<li><strong>' . esc_html_x('Logo:', 'CSS selector group name.', 'receptar') . '</strong><br />' . '<code>h1, .h1, blockquote</code>' . '</li>' . '</ol>' . '<p>' . sprintf(esc_html__('By default the theme uses %1$s font for texts, %2$s font for headings and %3$s font for logo.', 'receptar'), '<a href="http://www.google.com/fonts/specimen/Roboto" target="_blank">Roboto</a>', '<a href="https://www.google.com/fonts/specimen/Roboto+Condensed" target="_blank">Roboto Condensed</a>', '<a href="http://www.google.com/fonts/specimen/Alegreya" target="_blank">Alegreya</a>') . '</p>')); //Output return apply_filters('wmhook_receptar_theme_options_array_output', $options); }

hotexamples.com

Как и многие пользователи wordpress столкнулся с неполной русификацией нужной темы, а у нужных плагинов вообще русский язык отсутствовал. Пока пытался сделать красиво, собрал почти все грабли которые можно. Например про проблему с кодировкой я уже писал


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

Итак попробуем собрать всю информацию в одном месте и подробно разобрать как все-таки правильно русифицировать wordpress.

Я буду упоминать в тексте и плагины, и темы, потому что они русифицируются по одному принципу, так что можно не обращать на это внимание :)

Для начала нам нужно скачать программку для редактирования файлов локализаций poedit.

После того, как её установим нужно провести небольшие подготовительные работы. Для начала стоит разобраться поддерживает ли нужная нам тема или плагин различные локализации. Открываем папку с темой и ищем файлы с расширением .po .mo или .pot, обычно они находятся в папке language.

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

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

Теперь посмотрим что у нас имеется из языков. Возможны следующие варианты:


  1. Есть файл “название.pot”. Тогда нужно через меню “файл” в программе poedit выбрать “создать каталог из pot файла”, и рядом появится .po файл.
  2. Есть файлы “название-en_EN.po” или “en_EN.po”  и файл .mo с таким же названием. Как несложно догадаться en_EN это то, какой язык содержится в данном файле. В последних версиях WordPress все файлы с локализациями должны быть в формате “название-en_EN.po”, где “название” это название темы или плагина. Это название стоит запомнить, так как оно может пригодиться для исправления кода, чуть позже расскажу почему.
  3. Если никаких файлов нету, но нужно заглянуть в файлы темы и поискать там вывод текста. Если текст выводится с помощью функций похожих на __(), esc_attr_e(),_e() то poedit сможет выдернуть все тексты сама, ориентируясь на функции. (Подробнее описано чуть ниже, там же и будет полный список функций и как выдернуть текст.)
  4. Ну и если ничего подобного нет, значит тема или плагин не поддерживают локализацию или там какой-то свой механизм. Как я уже говорил в этом случае локализация выходит за рамки статьи.

На всякий случай в названии en это язык, а EN это страна. Например en_GB это британский английский, а en_US американский английский. В случае же en_EN страны с кодом EN нету и можно считать это общим случаем английского :) Все коды можно посмотреть тут для языков и тут для стран.

После того как мы разобрались с файлами и получили файл “.po”, делаем его копию и переименовываем в нужный нам язык. Например для плагина Theme My Login файл с русским языком стал выглядеть как “theme-my-login-ru_RU.po”

Теперь запускаем poedit и открываем наш файл.

Первое что надо сделать это объяснить программе каким образом работать с формами слов с числами, “1 комментарий” “2 комментария” и т.д. Для этого заходим в меню каталог->свойства и в поле “формы множественного числа” пишем (для русского языка)

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

Теперь сохраним файл (он должен сохранится без ошибок) и если файла .mo еще не было то он сгенерируется сам. Файл .mo это как раз и есть файл с переводом, просто он в бинарном виде и мало пригоден для редактирования.

Ну а теперь попробуем перевести какую-нибудь фразу. В poedit выделяем фразу для перевода и внизу будут 2 поля, одно с оригиналом, а в другое как раз и нужно ввести перевод. Еще там может быть несколько закладок, он как раз и переключают между разными формами слова для употребления с числительными.

После того как изменили несколько фраз, можно залить файлы на сайт и посмотреть на изменения. Если изменений не видно то для начала стоит проверить какой язык стоит в  wordpress по умолчанию. В wp-config.php ищем:

Ну или разбираемся с плагинами которые переключают язык, но это тоже выходит за рамки статьи :)

Если надписи все равно не изменились, то нужно проверить те ли надписи вообще пытаемся изменить. Для этого в poedit ткнем правой кнопкой мыши в надпись и посмотрим “связи”. Программа отобразит в каком файле и какой строке используется эта надпись. Если это действительно та надпись то сразу стоит проверить формат вызова функции, которая отвечает за локализацию.

Самые распространенные сейчас:

Основное отличие то что функция __() возвращает переведенное значение, а _e() выводит значение в поток. _n() используется если форма слова зависит от числительного, а _x() от контекста (например Post может означать статью или кнопку опубликовать).

Еще могут встречаться функции типа esc_attr__() или esc_html_e(), тоесть теже функции но перед ними дописано esc_attr или esc_html. Обе они экранируют специальные символы. esc_attr экранирует символы:

а esc_html экранирует эти символы и еще проверяет наличие неправильной кодировки utf-8.
Так вот, проблема с форматом часто встречается следующая:

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

Итак пример:

Если где-то в функцию не передается название, то вывод на других языках просто не будет работать. Это часто встречается в давно написанных плагинах, если автор поддерживает только одну локализацию. В старом коде он мог просто забыть исправить вызовы функций. Чтобы все заработало пройдемся поиском по названиям функций и просто добавим название. Не забываем выслать результаты трудов автору плагина или темы, он скорее всего скажет спасибо :)

Теперь перевод точно должен отображаться правильно.

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

Этот же список в немного измененном виде можно загрузить в poedit (каталог->свойства->ключевые слова исходных файлов). Тогда программа сама сможет проверить файлы темы на наличие этих функций, и добавить в файлы перевода недостающие фразы. Вот список для загрузки в редактор:

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

mecht.ru

Categories

hitchhackerguide.com

esc_attr

   $attr = '"there's nothing going on in here? Is there? >_<"';   echo esc_attr($attr);   // &quot;there&#039;s nothing going on in here? Is there? &gt;_&lt;&quot;  

The esc_attr function escapes content that is to be contained inside HTML attributes. titles, rels, etc.

esc_url and esc_url_raw

   $attr = 'https://inval1d.com?one=490&t"""\o=-1&c'ontent=<<<ONE>>!&amp;%00#one>';   echo esc_url($attr);   // https://inval1d.com?one=490&#038;to=-1&#038;c&#039;ontent=ONE!&#038;%00#one   echo esc_url_raw($attr);   // https://inval1d.com?one=490&to=-1&c'ontent=ONE!&amp;%00#on  

esc_url escapes a URL for display on pages. Invalid characters are simply stripped out, the others: a-z A-Z 0-9 - _ ~ : / ? # [ ] @ ! $ & ' ( ) * + , . ; = % are encoded into valid HTML entities (no, they’re not URL encoded, you have to do that yourself).

esc_url_raw wraps around esc_url but does not encode HTML entities, and is not meant to return data that can be safely displayed on pages. The function strips invalid URLs for storage.

The two functions do not allow URLs that have non-whitelisted schemes. The default schemes/protocols that are allowed are: ‘http’, ‘https’, ‘ftp’, ‘ftps’, ‘mailto’, ‘news’, ‘irc’, ‘gopher’, ‘nntp’, ‘feed’, ‘telnet’, ‘mms’, ‘rtsp’, ‘svn’ (no, no ‘magnet’ or ‘file’ protocols by default).

So, which one do you put as your href attribute in a link? esc_url encodes the entities, so an & is transformed into an &amp;. A user-fed URL should probably be escaped as esc_url_raw( $url );, to filter invalid URL characters and protocols, additionally esc_attr should be used to further encode the attribute as per HTML specification. (see StackOverflow: Do I encode Ampersands in a href?

esc_html

   $attr = '<div class="the" rel="quick" onclick="brown('fox')">jumped over...</div>';   echo esc_html($attr);   // &lt;div class=&quot;the&quot; rel=&quot;quick&quot; onclick=&quot;brown(&#039;fox&#039;)&quot;&gt;jumped over...&lt;/div&gt;  

esc_html is simple, it escapes any and all HTML, letting the browser render it instead of interpreting it. This is particularly useful for outputting code samples, especially those that come from the outside, via comments, etc.

esc_textarea

   $attr = 'This is some very nasty <script type="text/javascript">alert("XSS");</script> here!';   echo '<textarea>'.esc_textarea($attr).'</textarea>'; // make it safe  

esc_textarea is another important function, although not as convoluted and complex as esc_attr. esc_textarea sanitizes anything that is going to be displayed in a textarea element (enabled or disabled) and is similar to esc_html. esc_textarea uses htmlspecialchars().

esc_js

   $attr = "if ( !confirm('Are you sure you want to do this?') ) return false; alert('Done!');";   echo '<a href="#" onclick="alert('The payload: '.esc_js($attr).'');">clickme</a>';  

esc_js escapes all sorts of quote manipulations in strings that can lead to broken JavaScript strings. In order for this function to work the string has to be enclosed in single quotes. It can sometimes get confusing, especially when you’re echoing the JavaScript from PHP.

This function will not escape jQuery selectors like these jQuery('input[name=array[...]]'). It only escapes single-quoted strings.

esc_sql and like_escape

This is a convenient wrapper around the global $wpdb and its escape() method. Escapes SQL. esc_sql does NOT escape LIKE statements, an additional like_escape is available.

tag_escape and sanitize_html_class

tag_escape replaces anything other than a-zA-Z0-9_:, the set of valid HTML tag characters. sanitize_html_class does a similar operation on HTML classes, filtering out invalid stuff.


There are other escape functions that are used internally by WordPress, for key, username, title, filename sanitization. These can be used by themes and plugins; most are found inside wp-includes/formatting.php.

This escaping is quite confusing, isn’t it? Further contributing to the confusion is the fact that many built-in data generation methods may already escape data, like get_blogaddress_by_id. Ultimately, it’s up to you to check and sanitize/escape if necessary. And remember, future versions may remove built-in escaping from a function that you’re not escaping… ?

So, when was the last time you used esc_url inside a href attribute?

Published 7 years ago by soulseekah with 4 comments tagged core, plugins, security in WordPress

core plugins security WordPress

codeseekah.com

Написание HTML тегов

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

Чтобы код отображался как текст, а не понимался браузером как команды, достаточно заменить следующие спецсимволы на их сущности:

  • < на &lt;
  • > на &gt;
  • " на &quot;
  • & на &amp;

Таблица специальных символов и коды их сущностей

Символ (вид) Цифровой код HTML-код CSS-код Описание

<
&#60; &lt; �03C Знак «меньше чем» (начало тега)

>
&#62; &gt; �03E Знак «больше чем» (конец тега)

"
&#34; &quot; �022 Двойная кавычка

&
&#38; &amp; �026 Амперсанд

Теги PRE CODE XMP

Немного о тегах которые должны помочь, но не помогут или являются невалидными.
<pre> — «preformatted» — блочный элемент, который определяет блок предварительно форматированного текста.
<code> — строчный элемент, предназначенный для отображения одной или нескольких строк текста, который представляет собой программный код.
Эти теги оформляют текст, но не преобразуют его в сущности!!!

<xmp> — позволяет отображать фрагмент текста том виде, в каком он представлен внутри тега. Вот то что нам нужно для отображения сущностей! Но, к сожалению, он уже давно исключён из HTML-спецификации и его поддержка может быть прекращена любым браузером в любой момент.

PHP функции по преобразованию кода в сущности

Чтобы преобразовать код в сущности можно воспользоваться PHP функций htmlspecialchars(). Пример ее использования:

  <?php  echo htmlspecialchars("<div>HTML</div>", ENT_QUOTES);   // &lt;div&gt;HTML&lt;/div&gt;   ?>  

Необязательный второй аргумент quote_style определяет режим обработки одиночных и двойных кавычек. В режиме по умолчанию, ENT_COMPAT, преобразуются двойные кавычки, одиночные остаются без изменений. В режиме ENT_QUOTES преобразуются и двойные, и одиночные кавычки. а в режиме ENT_NOQUOTES и двойные, и одиночные кавычки остаются без изменений.

Если у вас WordPress, то используйте функцию esc_html_e().

  <?php esc_html_e('<div>HTML</div>'); //&lt;div&gt;HTML&lt;/div&gt;?>  

На экране в обоих случая будет выведено:

  <div>HTML</div>  

То есть код будет отображаться, а не выполняться.

moonback.ru


You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.