Должен ли я санировать адрес электронной почты перед передачей его функции is_email ()?

13

Я использую, is_email()чтобы проверить, действителен ли предоставленный пользователем адрес электронной почты. Например:

$email = $_POST['email'];
if ( is_email( $email ) )
    // Do something.

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

henrywright
источник
Кайзер, спасибо за редактирование. Это на самом деле санитария для меня, но я уверен, что большинство читателей здесь будут использовать z :)
Генрирайт

Ответы:

5

Если посмотреть на is_email()функциональность trac, похоже, что вам не нужно обрабатывать данные, так как это просто тестирование строк. Я бы даже сказал, что если эта функция возвращает значение true, вам не нужно очищать ее перед отправкой в ​​базу данных.

Howdy_McGee
источник
Мои мысли именно о струнном тестировании. Я думаю, что все еще продезинфицирую перед отправкой в ​​БД, вы, вероятно, правы, что в этом нет необходимости, но я нервничаю, когда дело доходит до этих вещей :)
henrywright
Правда, лучше, чем потом сожалеть, и затраты на санитарию были бы совершенно незаметны.
Howdy_McGee
18

WordPress и PHP ядро

is_email()Функция Source является типичной реализацией WordPress и не полностью работать с тем, что RFC 6531 позволяет. Одной из причин может быть то, что FILTER_VALIDATE_EMAILконстанта PHP по умолчанию для filter_var()не намного лучше при проверке чего-либо в соответствии с руководящими принципами Internet Engineering Task Force (IETF®) .

стандарты

Дело в том, что RFC 6531 допускает «символы Юникода за пределами диапазона ASCII» . А именно это (для локальной части - до @):

  • Прописные и строчные буквы английского алфавита (a – z, A – Z) (ASCII: 65–90, 97–122)
  • Цифры 0в 9(ASCII: 48–57)
  • Эти специальные символы: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Символ .(точка, точка, точка остановки) (ASCII: 46) при условии, что он не является первым или последним символом, а также при условии, что он не появляется последовательно (например John..Doe@example.com, не допускается).
  • Специальные символы допускаются с ограничениями. Они есть:
    • Космос и "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • Ограничения для специальных символов заключаются в том, что они должны использоваться только в том случае, если они заключены в кавычки, и что двум из них (обратный слеш \ и кавычка "(ASCII: 92, 34)) также должен предшествовать обратный слеш \(например, "\\"и "\"") ,
  • Комментарии допускаются с круглыми скобками в любом конце локальной части; Например, john.smith(comment)@example.comи (comment)john.smith@example.comоба эквивалентны "john.smith@example.com", но john.(comment)smith@example.comбудут недействительными.
  • Международные символы выше U+007F, закодированные как UTF-8, разрешены RFC 6531, хотя почтовые системы могут ограничивать какие символы использовать при назначении локальных частей.

и для глобальной / доменной части:

Часть имени домена в адресе электронной почты должна соответствовать строгим правилам: она должна соответствовать требованиям к имени хоста, состоящему из букв, цифр, дефисов и точек. Кроме того, доменная часть может быть литералом IP-адреса, заключенным в квадратные скобки, такие как jsmith@[192.168.2.1]или jsmith@[IPv6:2001:db8::1][…]

Источник: Википедия

Что действительно?

Это может привести к странным, но действительным адресам электронной почты, подобным следующему:

  • localpart.ending.with.dot.@example.com
  • (comment)localpart@example.com
  • "this is v@lid!"@example.com
  • "much.more unusual"@example.com
  • postbox@com
  • admin@mailserver1
  • "()<>[]:,;\\@\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org
  • " "@example.org

Источник: php.net / author gt@kani.hu - пример, исправленный автором этого поста

рамки

Существуют также локальные ограничения и ограничения длины домена:

Формат адресов электронной почты - это local-part@domainкогда локальная часть может иметь длину до 64 символов, а имя домена может содержать не более 253 символов, но максимальная длина 256 символов прямого или обратного пути ограничивает весь адрес электронной почты до быть не более 254 символов . [2] Формальные определения приведены в RFC 5322 (разделы 3.2.3 и 3.4.1) и RFC 5321 - с более читаемой формой, приведенной в информационном RFC 3696 [3] и связанных с ним ошибках. ,

Источник: Википедия

Ограничения WordPress

И вот что проверяет WordPress:

  • Проверить на минимальную длину письма можно: strlen( $email ) < 3
  • Проверить наличие символа @ после первой позиции: strpos( $email, '@', 1 ) === false
  • Тест на недопустимые символы: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Тест на последовательности периодов: preg_match( '/\.{2,}/', $domain )
  • Тест для ведущих и конечных периодов и пробелов: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Предположим, что в домене будет как минимум две подпрограммы: $subs = explode( '.', $domain );и затем
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Источник: WP Core v4.0

Фильтры и пользовательская проверка

Все вышеперечисленные случаи приведут is_email()к возврату false. Результат может фильтроваться (обратный вызов может быть присоединен), и у фильтра будет три аргумента, где последний аргумент является причиной. Пример:

return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );

Это означает, что вы можете переопределить результаты, возвращаемые определенными проверками.

Это позволяет добавлять специальные проверки, например, разрешать использование доменов Umlaut, частей домена только для TLD и т. Д.

Вывод

WordPress безопасен в большинстве случаев, но более ограничен, поскольку почтовые серверы должны соответствовать RFC. Имейте в виду, что не каждый почтовый сервер будет соответствовать рекомендациям RF 6531.

редактировать

Забавный побочный эффект: внутри есть две взаимосвязанные функции ~/wp-includes/formatting: is_email()и sanitize_email(). Они практически одинаковые функции. Я понятия не имею, почему кто-то решил, что было бы неплохо скопировать содержимое функции из одного в другое, вместо того, чтобы просто добавить одно в качестве обратного вызова к фильтрам, которые предоставляет другой. Поскольку v0.71 и v1.5 совпадают, я лично буду использовать позже, когда вы получите очищенную строку. Обратите внимание, что даже говорится, что он не соответствует RFC.is_email() sanitize_email() is_email()

кайзер
источник
Таким образом, вы говорите, что теоретически будут адреса электронной почты, которые полностью действительны в соответствии с RFC 6531, но WordPress сочтет их недействительными?
Генрирайт
Некоторые да. Например, домены только TLD, домены umlaut и т. Д., Как вы можете прочитать в последнем абзаце перед заключением в ответе. Пожалуйста, прочитайте ответ снова. Я знаю, это много, чтобы обернуть голову вокруг, но оно того стоит.
Кайзер
1
Я на самом деле уже прочитал это дважды, потому что это то, что стоит понять! Спасибо за такой подробный ответ :)
henrywright
2

Дезинфицировать все вещи!

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

JesseM
источник
Я думаю, что вы ударили по голове, когда сказали, что никогда не знаете, изменится ли реализация. Это может быть нормально, чтобы не дезинфицировать сейчас, но кто знает, изменится ли это позже?
Генрирайт