Convalida e-mail sicura

30

Ho utilizzato questa espressione regolare conforme a RFC822 per la convalida della posta elettronica. I pen tester su HackerOne hanno utilizzato i seguenti orrendi indirizzi e-mail che soddisfano la regex:

Gli indirizzi e-mail sono validi? Come posso fare una convalida e-mail sicura?

    
posta Randomblue 01.03.2016 - 09:40
fonte

5 risposte

39

Are those email addresses valid?

Sì, lo sono. Vedi ad esempio qui o con qualche spiegazione in più here .

Per una buona spiegazione su come possono apparire le email, consulta l'informativa RFC3696 . Anche le RFC più tecniche sono collegate qui.

Attacchi possibili nella parte locale di un indirizzo email

Without quotes, local-parts may consist of any combination of
alphabetic characters, digits, or any of the special characters

  ! # $ % & ' * + - / = ?  ^ _ ' . { | } ~

period (".") may also appear, but may not be used to start or end the local part, nor may two or more consecutive periods appear. Stated differently, any ASCII graphic (printing) character other than the at-sign ("@"), backslash, double quote, comma, or square brackets may appear without quoting. If any of that list of excluded characters are to appear, they must be quoted.

Quindi la regola è più o meno: la maggior parte dei caratteri può essere parte della parte locale, ad eccezione di @\",[] , quelli devono essere compresi tra " (tranne ovviamente " stesso, che deve essere sfuggito quando in una stringa quotata).

Ci sono anche regole su dove e quando quotare e come gestire i commenti, ma questo è meno rilevante per la tua domanda.

Il punto qui è che molti attacchi possono far parte della parte locale di un indirizzo email, ad esempio:

  • '/**/OR/**/1=1/**/--/**/@a.a
  • "<script>alert(1)</script>"@example.com
  • " onmouseover=alert(1) foo="@example.com
  • "../../../../../test%00"@example.com
  • ...

Attacchi possibili nella parte del dominio di un indirizzo email

La struttura esatta della parte del dominio può essere vista in RFC2822 o rFC5322 :

addr-spec       =       local-part "@" domain

local-part      =       dot-atom / quoted-string / obs-local-part

domain          =       dot-atom / domain-literal / obs-domain

domain-literal  =       [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]

dcontent        =       dtext / quoted-pair

dtext           =       NO-WS-CTL /     ; Non white space controls

                        %d33-90 /       ; The rest of the US-ASCII
                        %d94-126        ;  characters not including "[",
                                        ;  "]", or "\"

Dove:

   dtext           =   %d33-90 /          ; Printable US-ASCII
                       %d94-126 /         ;  characters not including
                       obs-dtext          ;  "[", "]", or "\"

Puoi vederlo di nuovo, la maggior parte dei caratteri è consentita (anche caratteri non ascii ). Possibili attacchi sarebbero:

  • [email protected]&a=////etc/passwd
  • foo@bar(<script>alert(1)</script>).com
  • foo@'/**/OR/**/1=1/**/--/**/

Conclusione

Non puoi convalidare gli indirizzi email in modo sicuro.

Invece, è necessario assicurarsi di avere delle difese adeguate (codifica HTML per XSS, istruzioni preparate per l'iniezione SQL, ecc.)

Come difesa in profondità, puoi proibire le stringhe e i commenti citati per ottenere una certa quantità di protezione, in quanto queste due cose consentono i caratteri e la stringa più insoliti. Ma alcuni attacchi sono ancora possibili e escluderai una piccola quantità di utenti.

Se hai bisogno di filtri di input aggiuntivi che superino i limiti del formato email, perché non ti fidi del resto della tua applicazione, dovresti considerare attentamente cosa autorizzi e cosa non permetti. Ad esempio, + viene utilizzato da Gmail per consentire il filtraggio dei messaggi di posta in arrivo, quindi non consentire agli utenti di non registrarsi. Altri caratteri possono essere utilizzati da altri provider per funzionalità simili. Un primo approccio potrebbe essere quello di consentire solo alfanum + ! # % * + - = ? ^ _ . | ~ . Ciò non consentirebbe < > ' " ' / $ { } & , che sono caratteri usati negli attacchi comuni. A seconda della tua applicazione, potresti voler disabilitare altri caratteri.

E come hai detto RFC822 : è un po 'obsoleto (è del 1982), ma anche consente stringhe e commenti tra virgolette, quindi è sufficiente dire che accetti solo gli indirizzi conformi a RFC822 non solo non sarà pratico, ma non funzionerà.

Inoltre, stai controllando le tue e-mail lato client? Il codice JS dà quell'impressione. Un utente malintenzionato potrebbe ignorare i controlli sul lato client.

    
risposta data 01.03.2016 - 10:31
fonte
10

Il modo più semplice per verificare ciò è provare a inviare un'email a quell'indirizzo, da un indirizzo di sola invio (ad esempio da [email protected]). Se non può essere consegnato, non è valido.

L'uso di una regex per analizzare le email è probabilmente il migliore dal lato client per far sapere loro in anticipo che potrebbero avere errori di battitura nel loro indirizzo email, prima che registrano.

    
risposta data 01.03.2016 - 10:21
fonte
8

Dici di voler disporre di sicuri indirizzi di posta elettronica. Presumo che questo significhi che questi vengono inseriti nella tua app e ti aspetti un risultato prevedibile. Gli sviluppatori che scrivono la tua app hanno nella testa collettiva qualche idea su cosa aspettarsi all'interno di un campo di posta elettronica, e è meglio non permettere ad altri di essere lì. Ciò che i tuoi programmatori non si aspettano non è molto sicuro (anche se è valido in base a qualche orribile RFC).

Quindi, se i tuoi sviluppatori non si occupano molto delle RFC relative alla posta elettronica, ti suggerisco di utilizzare "una violazione intenzionale di RFC 5322" che si verifica all'interno di uno standard W3C per HTML5 e che si traduce in una semplice espressione regolare:

^[a-zA-Z0-9.!#$%&'*+/=?^_'{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$

fonte link

Nel caso in cui questo è troppo lassista (se pensi che i tuoi sviluppatori non si aspettino quegli strani #$%&| etc), ti suggerisco di proteggerlo un po 'di più:

^[a-zA-Z0-9.+/=?^_-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$

Penso che il 99,9% degli indirizzi di persone reali corrisponda a entrambe queste espressioni.

    
risposta data 01.03.2016 - 21:54
fonte
4

Puoi passare troppo tempo a preoccuparti di questo genere di cose. Perché ti importa davvero tanto?

Non c'è un indirizzo veramente pericoloso in quanto tale: è quello che fai con esso / come lo tratti che conta.

Se elabori l'indirizzo in un modo non sicuro, ad es. concatenando una stringa per creare sql invece di usare i parametri, allora stai chiedendo dei problemi, non solo negli indirizzi email ma in ogni campo che stai permettendo all'utente di inserire.

In parole semplici; fornendo ha

[>= one char] @ [>= one char] . [>= one char]

o anche solo:

[>= one char] @ [>= one char]

dovresti accettarlo. Non importa cosa siano questi caratteri.

    
risposta data 02.03.2016 - 11:26
fonte
0

Le risposte che sottolineano la necessità di utilizzare un approccio a livelli piuttosto che affidarsi a un singolo filtro o difesa sono sulla strada giusta. Ci sono un sacco di articoli là fuori circa la scrittura della espressione regolare 'corretta' per convalidare un indirizzo mail. La realtà è che è necessario combinare un numero di controlli e non basarsi solo su una espressione regolare.

Quali controlli hai bisogno dipenderà da cosa stai cercando di fare e da quali rischi stai cercando di proteggere. Se stai solo cercando di identificare gli spammer, potresti dover controllare anche il contenuto, le righe dell'oggetto e i server di posta originari. D'altra parte, se stai provando a verificare un indirizzo mail per un processo di registrazione, potresti voler verificare il dominio, eventualmente aggiungere un processo di conferma che manda un messaggio all'indirizzo ecc.

Il mio consiglio è simile a @MattWilko - presto ti ritrovi a ottenere rendimenti decrescenti quando cerchi di ottenere la regexp perfetta. Man mano che la tua espressione diventa più complessa, prenderai più indirizzi sbagliati, ma quasi certamente aumenterai anche il numero di falsi positivi. La chiave è trovare il giusto equilibrio e tale equilibrio dipenderà dal tuo caso d'uso e dai rischi che stai cercando di proteggere.

    
risposta data 04.03.2016 - 02:49
fonte

Leggi altre domande sui tag