Czy powinienem zdezynfekować adres e-mail przed przekazaniem go do funkcji is_email ()?

13

Używam, is_email()aby sprawdzić, czy adres e-mail podany przez użytkownika jest prawidłowy. Na przykład:

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

Według mojej najlepszej wiedzy, nic w tej funkcji nie zapisuje informacji w bazie danych. Czy powinienem dezynfekować, $emailzanim przekażę to funkcji?

henrywright
źródło
Kaiser, dzięki za edycję. To właściwie dla mnie sanityation, ale jestem pewien, że większość czytelników tutaj użyje z :)
henrywright

Odpowiedzi:

5

Patrząc na is_email()funkcjonalność trac, wygląda na to, że nie musisz się sanatizie, ponieważ to tylko testowanie ciągów. Chciałbym nawet posunąć się do stwierdzenia, że ​​jeśli ta funkcja zwróci wartość true, nie trzeba jej dezynfekować przed wysłaniem jej do bazy danych.

Howdy_McGee
źródło
Moje myśli dokładnie o testowaniu ciągów. Myślę, że nadal będę dezynfekować przed wysłaniem do bazy danych, prawdopodobnie masz rację, że nie jest to konieczne, ale jestem zdenerwowany, jeśli chodzi o te rzeczy :)
henrywright
To prawda, lepiej bezpieczny niż żałować, a koszty sanityzacji byłyby całkowicie niezauważalne.
Howdy_McGee
18

WordPress i rdzeń PHP

is_email()Funkcja Źródło to typowa realizacja WordPress i nie w pełni współpracować z co RFC 6531 pozwala. Jednym z powodów może być to, że domyślna FILTER_VALIDATE_EMAILstała PHP filter_var()nie jest dużo lepsza w sprawdzaniu poprawności zgodnie z wytycznymi The Internet Engineering Task Force (IETF®) .

Standardy

Chodzi o to, że RFC 6531 zezwala na „znaki Unicode spoza zakresu ASCII” . Mianowicie są to (dla części lokalnej - przed @):

  • Wielkie i małe litery angielskie (a – z, A – Z) (ASCII: 65–90, 97–122)
  • Cyfry 0do 9(ASCII: 48–57)
  • Te znaki specjalne: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Znak .(kropka, kropka, kropka) (ASCII: 46) pod warunkiem, że nie jest to pierwszy lub ostatni znak, i pod warunkiem, że nie pojawia się po kolei (np. [email protected]Nie jest dozwolony).
  • Znaki specjalne są dozwolone z ograniczeniami. Oni są:
    • Spacja i "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • Ograniczenia dotyczące znaków specjalnych są takie, że należy ich używać tylko wtedy, gdy znajdują się między znakami cudzysłowu, oraz że 2 z nich (odwrotny ukośnik \ i cudzysłów "(ASCII: 92, 34)) musi również być poprzedzony odwrotnym ukośnikiem \(np. "\\"I "\"") .
  • Komentarze są dozwolone w nawiasach na obu końcach części lokalnej; np. john.smith(comment)@example.comi (comment)[email protected]oba są równoważne "[email protected]", ale john.(comment)[email protected]byłyby nieprawidłowe.
  • Znaki międzynarodowe powyżej U+007F, zakodowane jako UTF-8, są dozwolone przez RFC 6531, chociaż systemy pocztowe mogą ograniczać, których znaków używać podczas przypisywania części lokalnych.

a dla części globalnej / domeny:

Nazwa domeny adresu e-mail musi być zgodna z surowymi wytycznymi: musi spełniać wymagania dotyczące nazwy hosta, składającej się z liter, cyfr, łączników i kropek. Ponadto część domeny może być literałem adresu IP, otoczonym nawiasami kwadratowymi, takimi jak jsmith@[192.168.2.1]lub jsmith@[IPv6:2001:db8::1][…]

Źródło: Wikipedia

Co jest ważne

Może to prowadzić do dziwnych, ale prawidłowych adresów e-mail, takich jak:

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

Źródło: php.net / autor [email protected] - przykład ustalony przez autora tego postu

Granice

Istnieją również limity długości lokalnych i domen:

Format adresów e-mail polega na local-part@domaintym, że część lokalna może mieć do 64 znaków, a nazwa domeny może mieć maksymalnie 253 znaki - ale maksymalna długość 256 znaków w ścieżce do przodu lub do tyłu ogranicza cały adres e-mail do nie może mieć więcej niż 254 znaków . [2] Formalne definicje podano w RFC 5322 (sekcje 3.2.3 i 3.4.1) i RFC 5321 - z bardziej czytelną formą podaną w informacyjnym RFC 3696 [3] i związanej z nim erracie .

Źródło: Wikipedia

Ograniczenia WordPress

I właśnie to sprawdza WordPress:

  • Sprawdź minimalną długość wiadomości e-mail: strlen( $email ) < 3
  • Przetestuj znak @ po pierwszej pozycji: strpos( $email, '@', 1 ) === false
  • Testuj nieprawidłowe znaki: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Testuj ciągi okresów: preg_match( '/\.{2,}/', $domain )
  • Testowanie wiodących i końcowych okresów oraz białych znaków: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Załóżmy, że domena będzie mieć co najmniej dwa subskrybcje: $subs = explode( '.', $domain );a następnie
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Źródło: WP Core v4.0

Filtry i niestandardowe sprawdzanie poprawności

Wszystkie wyżej wymienione przypadki powodują is_email()zwrócenie wartości false. Rezultat jest filtrowalny (można dołączyć wywołanie zwrotne), a filtr będzie miał trzy argumenty, z których ostatni argument jest przyczyną. Przykład:

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

co oznacza, że ​​możesz zastąpić wyniki zwrócone przez określone kontrole.

Umożliwia to dodawanie specjalnych kontroli, na przykład w celu umożliwienia domen Umlaut, części domeny tylko TLD itp.

Wniosek

WordPress jest bezpieczny w większości przypadków, ale bardziej restrykcyjny, ponieważ serwery pocztowe muszą być zgodne z RFC. Pamiętaj, że nie każdy serwer pocztowy będzie zgodny z wytycznymi RF 6531.

Edytować

Zabawny efekt uboczny: wewnątrz są dwie powiązane funkcje ~/wp-includes/formatting: is_email()i sanitize_email(). Są praktycznie taką samą funkcją. Nie mam pojęcia, dlaczego ktoś zdecydował, że dobrym pomysłem byłoby skopiowanie zawartości funkcji z jednej strony na drugą zamiast dodawania jednej jako wywołania zwrotnego do filtrów, które zapewnia drugi. Ponieważ od v0.71 i od v1.5 są takie same, ja osobiście użyłby później jak dostać czyszczone ciąg. Zauważ, że nawet stwierdza, że ​​nie jest zgodny z RFC.is_email() sanitize_email() is_email()

kajzer
źródło
Mówisz więc, że teoretycznie będą tam adresy e-mail, które są całkowicie poprawne zgodnie z RFC 6531, ale WordPress uzna je za nieprawidłowe?
henrywright
Niektóre tak. Na przykład domeny tylko TLD, domeny umlaut itp., Jak można przeczytać w ostatnim akapicie przed zakończeniem odpowiedzi. Przeczytaj ponownie odpowiedź. Wiem, że warto się owinąć, ale warto.
kaiser
1
Właściwie już to przeczytałem dwa razy, ponieważ warto to zrozumieć! Dzięki za tak szczegółową odpowiedź :)
henrywright
2

Odkaż wszystkie rzeczy!

Jedną z głównych zasad bezpieczeństwa jest nigdy nie ufać wkładowi użytkownika. Zasadniczo nie dbam o implementację is_email () lub jakiejkolwiek innej konkretnej funkcji, czy też ta funkcja robi coś niebezpiecznego z tym, co jej daję. Może implementacja zmieni się pewnego dnia. Kto wie. Muszę założyć, że można to skompromitować. Założeniem powinno być zawsze to, że dane wejściowe użytkownika są aktywnie wrogie, podwójnie, więc w przypadku wszystkiego, co ostatecznie jest przeznaczone dla bazy danych, i aby zdezynfekować każdy fragment danych wejściowych użytkownika przed przekazaniem go jakiejś funkcji. To tylko dobra, ogólna higiena bezpieczeństwa.

JesseM
źródło
Myślę, że trafiłeś w sedno, kiedy powiedziałeś, że nigdy nie wiesz, czy wdrożenie się zmieni. Może nie być teraz higieniczne, ale kto wie, czy to się zmieni w późniejszym terminie?
henrywright