Devo disinfettare un indirizzo e-mail prima di passarlo alla funzione is_email ()?


13

Sto usando is_email()per verificare se un indirizzo e-mail fornito dall'utente è valido. Per esempio:

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

Per quanto ne so, nulla in questa funzione scrive informazioni nel database. Devo disinfettare $emailprima di passare alla funzione?


Kaiser, grazie per la modifica. In realtà è una sanificazione per me, ma sono sicuro che la maggior parte dei lettori qui utilizzerà una z :)
henrywright,

Risposte:


5

Osservando la is_email()funzionalità su trac, sembra che non sia necessario sanatizie in quanto si tratta solo di test delle stringhe. Vorrei anche dire che se questa funzione ritorna vera, non sarebbe necessario disinfettarla prima di inviarla nel database.


I miei pensieri esattamente sul test delle stringhe. Penso che continuerò a disinfettare prima di inviarlo al db, probabilmente hai ragione che non è necessario, ma sono un
disastro

Vero, meglio prevenire che curare e il sovraccarico di sanificazione sarebbe del tutto impercettibile.
Howdy_McGee

18

WordPress e core PHP

La is_email()funzione Source è una tipica implementazione di WordPress e non funziona completamente con ciò che RFC 6531 consente. Un motivo potrebbe essere che la FILTER_VALIDATE_EMAILcostante PHP predefinita per filter_var()non è molto meglio nel validare qualcosa secondo le linee guida IETF® .

Standards

Il punto è che RFC 6531 consente "Caratteri Unicode oltre l'intervallo ASCII" . Vale a dire quelli sono (per la parte locale - prima del @):

  • Lettere inglesi maiuscole e minuscole (a – z, A – Z) (ASCII: 65–90, 97-122)
  • Cifre 0su 9(ASCII: 48–57)
  • Questi personaggi speciali: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Carattere .(punto, punto, punto e virgola) (ASCII: 46) purché non sia il primo o l'ultimo carattere e purché non appaia consecutivamente (ad es. John..Doe@example.comNon consentito).
  • Sono ammessi caratteri speciali con restrizioni. Loro sono:
    • Spazio e "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • Le restrizioni per i caratteri speciali sono che devono essere usate solo se racchiuse tra virgolette e che 2 di esse (la barra rovesciata \ e le virgolette "(ASCII: 92, 34)) devono anche essere precedute da una barra rovesciata \(ad es. "\\"E "\"") .
  • Sono consentiti commenti tra parentesi alle estremità della parte locale; ad esempio john.smith(comment)@example.come (comment)john.smith@example.comsono entrambi equivalenti a "john.smith@example.com", ma non john.(comment)smith@example.comsarebbero validi.
  • I caratteri internazionali sopra U+007F, codificati come UTF-8, sono consentiti da RFC 6531, sebbene i sistemi di posta elettronica possano limitare quali caratteri usare quando si assegnano parti locali.

e per la parte globale / dominio:

La parte del nome di dominio di un indirizzo e-mail deve essere conforme a rigide linee guida: deve corrispondere ai requisiti per un nome host, costituito da lettere, cifre, trattini e punti. Inoltre, la parte del dominio può essere un indirizzo IP letterale, circondata da parentesi quadre, come jsmith@[192.168.2.1]o jsmith@[IPv6:2001:db8::1][…]

Fonte: Wikipedia

Cosa è valido

Questo può portare a indirizzi di posta elettronica strani ma validi come i seguenti:

  • 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

Fonte: php.net / autore gt@kani.hu - esempio risolto dall'autore di questo post

limiti

Esistono anche limiti di lunghezza locali e di dominio:

Il formato degli indirizzi e-mail è local-part@domaindove la parte locale può contenere fino a 64 caratteri e il nome di dominio può avere un massimo di 253 caratteri , ma la lunghezza massima di 256 caratteri di un percorso in avanti o indietro limita l'intero indirizzo e-mail a non deve contenere più di 254 caratteri . [2] Le definizioni formali sono in RFC 5322 (sezioni 3.2.3 e 3.4.1) e RFC 5321 - con una forma più leggibile fornita nell'informativa RFC 3696 [3] e gli errori associati .

Fonte: Wikipedia

Restrizioni di WordPress

E questo è ciò che WordPress controlla per:

  • Prova per la lunghezza minima che l'e-mail può essere: strlen( $email ) < 3
  • Prova un carattere @ dopo la prima posizione: strpos( $email, '@', 1 ) === false
  • Test per caratteri non validi: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Test per sequenze di periodi: preg_match( '/\.{2,}/', $domain )
  • Test per periodi iniziali e finali e spazi bianchi: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Supponiamo che il dominio abbia almeno due sottotitoli: $subs = explode( '.', $domain );e quindi
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Fonte: WP Core v4.0

Filtri e convalida personalizzata

Tutti i casi sopra menzionati si innescheranno is_email()per restituire false. Il risultato è in grado di filtrare (è possibile allegare un callback) e il filtro avrà tre argomenti, dove l'ultimo argomento è il motivo. Esempio:

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

ciò significa che è possibile ignorare i risultati restituiti da controlli specifici.

Ciò consente di aggiungere controlli speciali, ad esempio per consentire domini Umlaut, parti di dominio solo TLD, ecc.

Conclusione

WordPress è sicuro per la maggior parte dei casi, ma più restrittivo in quanto i server di posta devono effettivamente essere conformi a RFC. Tenere presente che non tutti i server di posta si allineano alle linee guida RF 6531.

modificare

Funny sidefact: ci sono due funzioni correlate all'interno ~/wp-includes/formatting: is_email()e sanitize_email(). Sono praticamente la stessa funzione. Non ho idea del perché qualcuno abbia deciso che sarebbe una buona idea copiare il contenuto della funzione da uno all'altro invece di aggiungere semplicemente uno come callback ai filtri che l'altro fornisce. Dal momento che v0.71 e poiché v1.5 sono uguali, personalmente userei il successivo quando otterrai una stringa pulita. Si noti che afferma persino che non è conforme a RFC.is_email() sanitize_email() is_email()


Quindi stai dicendo, in teoria, che ci saranno indirizzi e-mail là fuori che sono completamente validi secondo RFC 6531 ma questi saranno considerati non validi da WordPress?
henrywright,

Alcuni si. Ad esempio domini solo TLD, domini umlaut, ecc. Come puoi leggere nell'ultimo paragrafo prima della conclusione nella risposta. Si prega di leggere di nuovo la risposta. So che è molto complicato, ma ne vale la pena.
Kaiser

1
In realtà l'ho già letto due volte perché è qualcosa che vale la pena capire! Grazie per una risposta così dettagliata :)
henrywright il

2

Disinfetta tutte le cose!

Una delle regole cardine della sicurezza è non fidarsi mai dell'input dell'utente. In generale, non mi interessa l'implementazione di is_email () o di qualsiasi altra funzione specifica, o se quella funzione fa qualcosa di pericoloso con ciò che gli do. Forse l'implementazione cambierà un giorno. Chissà. Devo presumere che possa essere compromesso. Il presupposto dovrebbe essere sempre che l'input dell'utente sia attivamente ostile, doppiamente per qualsiasi cosa eventualmente destinata a un database, e di disinfettare ogni bit di input dell'utente prima di consegnarlo a qualche funzione. Questa è solo una buona igiene generale della sicurezza.


Penso che tu abbia colpito l'unghia sulla testa quando hai detto che non sai mai se l'implementazione cambierà. Potrebbe essere OK non disinfettare ora, ma chissà se ciò cambierà in un secondo momento?
henrywright,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.