Должны ли сообщения об ошибке WP уже быть экранированы в формате html?


Речь идет не о том, что такое экранирование html или как это делается, а о том, существует ли устоявшаяся передовая практика в отношении того, когда это делать.

У меня есть некоторый служебный код в моем плагине, который может генерировать WP_Error на основе пользовательского ввода, и другой код отображения, который показывает, что WP_Error. Конечно, этот пользовательский ввод должен быть экранирован в формате html при отображении, но я не уверен, когда будет лучшее время для этого.

У меня есть выбор, следует ли:

  • Избежать сообщение, когда я строю WP_Error, и код отображения показывает его как есть.

  • Не беспокойтесь об экранировании при построении WP_Error, и в коде отображения полностью экранируйте все сообщения WP_Error.

Либо сработает, но если мой плагин будет взаимодействовать с другими плагинами и, возможно, отображать их WP_Error или наоборот, я хотел бы соответствовать любому прецеденту, существующему в мире Wordpress.

Я надеялся, что в документации будет рассмотрен этот вопрос, но я ничего не видел на https://codex.wordpress.org/Class_Reference/WP_Error

Author: Jason Viers, 2019-01-13

4 answers

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

Убегая, мы говорим о таких функциях, как esc_html, wp_kses_post, esc_url, и т.д.

Функции очистки и функции проверки не одно и то же, напримерsanitize_textfield. Очистка очищает данные, проверка проверяет данные, экранирование обеспечивает соблюдение типа данных.

Подумайте об этом так для фабрики треугольников:

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

Двойной побег это плохо, потому что если мы затем возьмем наш сломанный квадрат в форме треугольника, перевернем его вверх дном и пропустим его через резак для печенья во второй раз, мы получим не треугольник, а шестиугольник. Нам не нужны были шестиугольники!

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


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

Если бы мы выполнили побег при вводе, нам пришлось бы либо выполнить двойной побег, либо доверять всем объектам WP_Error, что не является стартером. Все, что для этого потребуется, - это один разработчик плагина, забывающий сбежать при вводе. Также намного проще сбежать в одном месте, которое выводит, чем сбежать во многих местах, которые вводят.

Поэтому вместо этого код, который получает и выводит объект WP_Error там, где должно быть экранирование, таким образом, мы безопасно выходим на выходе, зная, что никакого раннего экранирования не произошло, двойного экранирования не происходит, независимо от того, был ли он экранирован, это не проблема, с которой нам приходится иметь дело, и ответственность за побег ясна и прямолинейна

Что касается того, как безопасно вывести объект WP_Error, то достаточно esc_html или wp_kses_post . Последнее позволит использовать такие теги, как <strong> и т.д. Как правило, ставя что-либо более сложное в объекте ошибки, чем то, что вы бы поместили в сообщение, - плохая идея, WP_Error объекты уже являются структурированными данными

 2
Author: Tom J Nowell, 2019-01-14 17:01:35

Это очень хороший вопрос.

WP_Error класс ничего не делает с заданными вами сообщениями. Итак, что вы устанавливаете, то и получаете;)

С другой стороны, сообщения об ошибках могут содержать HTML, поэтому вы не можете избежать их всех при печати ошибок. Например, здесь вы получаете сообщение из файла wp-login.php:

$errors->add('empty_username', __('<strong>ERROR</strong>: Enter a username or email address.'));

И, чтобы сделать все еще сложнее, как вы можете видеть, оно передается через функцию __(), поэтому после перевода сообщение может содержать еще больше HTML-тегов.

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

 2
Author: Krzysiek Dróżdż, 2019-01-13 20:37:02

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

Я не могу добавить больше к тому, что уже сказал Том, ответ на ваш первоначальный вопрос "нет", так как я повторюсь в конце этого ответа, сообщение WP_Error - это чистая строка, которая не должна содержать ничего, кроме простых символов, готовых к использованию в любом система. Добавление разметки или чего-то подобного в них противоречит их цели, но есть большая вещь, о которой вы, вероятно, не знаете.

Перевод и отображение этого перевода.

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

Виновником является Polylang, но это не его вина, каждый перевод плагин будет вести себя так, они никогда не покинут свои переведенные строки. На их экранах и как они это хранят, конечно, это работа плагинов, но то, что вы делаете со строкой после того, как плагин передал ее вам, - ваша работа.

Итак, как это работает?

Интегрируйте строку с Polylang, но вместо обычной строки поместите это в:

<body onload=alert('XSS')>

Теперь, когда вы повторяете эту переведенную строку, где бы это ни произошло, вы получите всплывающее окно:

enter image description here

Если бы вы просто избежали этого, это никогда не было бы проблемой. Проблема здесь в том, что если вы предоставили права на перевод пользователям или где-то еще есть дыра в самом плагине, которая позволяет пользователям запускать "изменить строку перевода", ваш сайт взломан. На самом деле, если у вас есть файлы перевода, и кто-то вставляет какие-либо JS, и вы не выводите их правильно, и вы принимаете этот перевод, и он отправляется в хранилище, кто-нибудь тот, кто использует этот пакет перевода, будет иметь вредоносный JS на своем сайте, этого, вероятно, никогда не произойдет, но просто расскажет вам.

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

echo fav_plugin_output_translated_string( 'string-1' ) // will output whatever matches

Что может быть вредоносным, как таковое, если плагин не имеет встроенной функции escape, сделайте это, в зависимости от того, где вам нужна эта строка, но это в 99% случаев для отображения в HTML:

echo esc_html( fav_plugin_output_translated_string( 'string-1' ) );

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

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

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

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

 2
Author: coolpasta, 2019-01-17 08:03:41

Лично я бы сохранил сообщения об ошибках в основном в виде обычного текста и статических (не включающих ввод пользователя) - из того, что я видел, большинство плагинов придерживаются такого мышления, когда сообщения об ошибках являются короткими текстовыми заметками о том, что пошло не так. Это позволяет вам использовать такие сообщения, как "Пароль слишком короткий" или "У MYPASS не хватает пароля".

Если вам нужен какой-то HTML-код в самом сообщении об ошибке, я бы избавился от него по пути.

$error = new WP_Error();

$message = "The correct tag is <strong></strong>";
$html_ok_message = htmlspecialchars($message);

$error->add($code, $html_ok_message, $data);

Вы могли бы избежать их на выходе, если бы вы знайте, что все возможные возникшие ошибки не содержат HTML-кода, который необходимо отображать. Если вы всегда избегаете их всех при выводе, вы, скорее всего, получите такие вещи, как &lt;strong;Error&gt; Something went wrong in XY_Other_plugin .

 1
Author: DACrosby, 2019-01-13 20:45:14