В каких контекстах плагины отвечают за проверку данных / санитарную обработку?

17

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

В рамках этого вопроса меня не интересует проверка данных на уровне домена - например, проверка того, что поле возраста в форме находится в диапазоне от 0 до 120 или что адрес электронной почты является действительным. Меня беспокоит только безопасность - например, экранирование запросов SQL, чтобы избежать внедрения SQL при сохранении в базу данных, или санация данных, которые выводятся в шаблоны HTML, чтобы избежать XSS.

Я знаю, что для очистки выходных данных вам всегда нужно использовать такие функции, как esc_html()и esc_attr()при выводе переменных в шаблоны HTML. Но как насчет использования тегов шаблона ? Они все уже санируют выход? Если да, то для какого контекста (общий HTML, атрибуты тегов и т. Д.)? Некоторые функции имеют варианты для разных контекстов (например the_title_attribute(), но большинство не имеют.

Для очистки ввода я знаю, что мне нужно использовать $wpdb->prepare()при выполнении запросов вручную, но как насчет использования API настроек для создания страницы настроек плагина или сохранения мета-полей поста для пользовательского типа поста?

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

API проверяет / дезинфицирует

  • Сохранение мета-записи с update_postmeta()
  • Сохранение мета пользователя с update_user_meta()
  • Вывод заголовка поста - используйте контекстуально подходящий вариант the_title()
  • и т.д

Вы должны вручную проверить / продезинфицировать

  • Сохранение параметров плагина с помощью API настроек. Передайте обратный вызов в качестве 3-го параметра register_setting().
  • Прямые запросы к базе данных: заверните запрос в $wpdb->prepare().
  • Вывод переменных в HTML. Использование esc_attr(), esc_html()и т.д.
  • и т.д

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

Ян Данн
источник
Мне нравится этот вопрос. У меня такая же мысль, как и у тебя. Я думаю, если бы был такой список, когда мы должны проверять / очищать вручную, это было бы здорово. +1.
Ань Чан
1
@ Rilwis, пожалуйста, посмотрите мой ответ. Вы должны всегда подтверждать. Санитаризация сложнее, поскольку «безопасность» зависит от контекста. Как правило, если вы используете WordPress API с данными, известными WordPress ( the_title()и the_permalink()т. Д.), У вас все хорошо, но с пользовательскими данными у вас нет (например get_post_meta()). Если сомневаетесь, санируйте себя - это не повредит.
Стивен Харрис
@StephenHarris: я прочитал ваш комментарий. Я тоже это знаю. Но у меня такое же мнение, как у Яна Данна. Я думаю, что главная причина, по которой он спрашивает: «делай достаточно, не больше, не меньше».
Ань Чан
1
На самом деле, я не против ошибиться и сделать слишком много проверок / санитарии, но я думаю, что бывают случаи, когда можно дважды избежать проблем.
Ян Данн

Ответы:

15

Здесь есть две концепции:

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

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

Санитарная обработка немного более смешанная. Имея дело с данными, о которых WordPress изначально знает (например, плиткой сообщения), вы можете быть уверены, что WordPress уже сделал данные безопасными. Однако «безопасный» зависит от контекста; то, что безопасно для использования на странице, не обязательно безопасно как атрибут элемента. Поэтому WordPress будут иметь разные функции для разного контекста (например the_title(), the_title_rss(), the_title_attribute()) - так что вы должны использовать правильный .

По большей части ваш плагин может иметь дело с мета-постом или, возможно, данными о событиях из пользовательской таблицы. WordPress не знает, что это за данные или для чего они нужны, поэтому, конечно, не знает, как сделать их безопасными. Это зависит от вас . Это особенно важно при использовании esc_url(), esc_attr(), и esc_textarea()т.д. , чтобы предотвратить злонамеренный ввод от возможности вставлять код. Так как WordPress знает next_posts(), что нужно напечатать URL-адрес страницы, он применяется esc_url()- но, скажем, с мета-публикацией он не знает, что он хранит URL-адрес - или что вы хотите с ним делать (при печати esc_url(), при перенаправлении) esc_url_raw(). Если вы добросовестны - соблюдайте осторожность и избегайте этого сами - и делайте это как можно позже.

Наконец - как насчет сохранения данных? Вы должны сделать это тогда? Как уже упоминалось вам сделать необходимо убедиться , что данные верны. Но если вы используете WordPress API ( wp_insert_post()и update_post_meta()т. Д.), Вам не нужно очищать данные - потому что при сохранении данных единственное, что вам нужно сделать - это избежать операторов SQL - и WordPress делает это. Если вы выполняете прямые операторы SQL (скажем, для чтения / записи данных из пользовательской таблицы), то вам следует использовать $wpdbкласс, чтобы помочь вам санировать ваши запросы.

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

Стивен Харрис
источник
Привет, Стефан, спасибо за объяснение. Это помогло мне понять это немного лучше, но то, что я действительно ищу, это своего рода полный список, как пример, который я привел. Похоже, ваш подход состоит в том, чтобы сделать обоснованное предположение о том, справится ли WP с этим или нет, или сделать ошибку с осторожностью и всегда проводить санитарную обработку. Я чувствовал бы себя более уверенно, если бы у меня был авторитетный и всеобъемлющий список, а не полагаться на свое понимание этого. Я также обеспокоен тем, что двойной выход может привести к проблемам.
Ян Данн
Я также только что обновил вопрос, чтобы уточнить некоторые вещи.
Ян Данн
0

Не уверен, что это так тщательно, но с любым плагином или темой пользовательский ввод должен быть очищен. Операции с базой данных должны выполняться с использованием методов $ wpdb->. Все данные $ _GET и $ _POST должны быть очищены.

Это лучшая практика для программирования PHP, чем WordPress.

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

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

Киприан
источник
3
Я понимаю, что его всегда нужно дезинфицировать, но вопрос в том, кто проводит санитарию в каждой конкретной ситуации. Иногда WordPress делает это автоматически, а иногда вам приходится делать это вручную. Я обновил вопрос, чтобы попытаться сделать его более понятным.
Ян Данн
Даже при использовании update_user_meta () вам все равно необходимо его проверить, так как обновленные значения могут поступать из открытой формы или из пользовательского ввода. Если это значение, полученное из скрипта, такого как внутреннее решение, из цикла if / else, то вы не должны его дезинфицировать.
Ciprian
1
Значение, которое вы передаете, update_user_meta()проходит через stripslashes_deep()и sanitize_meta()в update_metadata(), а затем $wpdb->prepare()в $wpdb->update(). Так что я не думаю, что вам нужно его дезинфицировать. Я что-то пропустил?
Ян Данн