web-dev-qa-db-ja.com

安全なメール検証

電子メールの検証に このRFC822準拠の正規表現 を使用しています。 HackerOneのペンテスターは、正規表現を満たす次の恐ろしいメールアドレスを使用しました。

それらのメールアドレスは有効ですか?安全なメール検証を行うにはどうすればよいですか?

32
Randomblue

それらのメールアドレスは有効ですか?

はい、そうです。たとえば here を参照するか、もう少し説明 here を参照してください。

電子メールがどのように見えるかについての良い説明は、情報 RFC3696 を参照してください。より技術的なRFCもそこでリンクされています。

メールアドレスのローカル部分で攻撃が可能

引用符がなければ、ローカル部分は、
アルファベット文字、数字、またはその他の特殊文字

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

ピリオド( "。")も表示されますが、ローカルパーツの開始または終了に使用することはできません。また、2つ以上の連続するピリオドが表示されることもありません。別の言い方をすると、アットマーク( "@")、バックスラッシュ、二重引用符、コンマ、または角括弧以外のASCIIグラフィック(印刷)文字は、引用符なしで表示される場合があります。除外する文字のリストを表示するには、引用符で囲む必要があります。

つまり、ルールは多かれ少なかれ:@\",[]を除いて、ほとんどの文字はローカル部分の一部になることができますが、それらは"の間にある必要があります(もちろん、"自体は、引用符付き文字列内でエスケープする必要があります)。

引用する場所とタイミング、コメントの処理方法に関するルールもありますが、それは質問との関連性が低くなります。

ここでのポイントは、多くの攻撃が電子メールアドレスのローカル部分の一部になる可能性があることです。次に例を示します。

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

メールアドレスのドメイン部分で攻撃が可能

ドメイン部分の正確な構造は RFC2822 または 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 "\"

どこ:

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

再び、ほとんどの文字が許可されていることがわかります( 非ASCII文字 でも)。考えられる攻撃は次のとおりです。

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

結論

メールアドレスを安全に検証することはできません。

代わりに、適切な防御策(XSSのHTMLエンコーディング、SQLインジェクション用の準備済みステートメントなど)を確実に用意する必要があります。

詳細な防御策として、引用符で囲まれた文字列とコメントを保護して、ある程度の保護を得ることができます。これは、これらの2つの要素により、最も珍しい文字と文字列が許可されるためです。ただし、一部の攻撃は依然として可能であり、少量のユーザーを除外します。

メール形式の制限を超える追加の入力フィルタリングが必要な場合は、アプリケーションの残りを信頼しないため、許可するものと許可しないものを慎重に検討する必要があります。たとえば、+は受信メールのフィルタリングを許可するためにgmailによって使用されるため、許可しないとユーザーがサインアップしない可能性があります。他の文字は、同様の機能のために他のプロバイダーによって使用される場合があります。最初のアプローチは、alphanum + ! # % * + - = ? ^ _ . | ~のみを許可することです。これは、一般的な攻撃で使用される文字である< > ' " ` / $ { } &を許可しません。アプリケーションによっては、これ以上の文字を禁止したい場合があります。

そして、あなたが言及したように RFC822 :少し古くなっています(1982年からです)が、引用符で囲まれた文字列とコメントを許可しているため、RFC822準拠のアドレスのみを受け入れると言うだけでは、実用的ではありません、しかしまた動作しません。

また、クライアント側でメールをチェックしていますか? JSコードはその印象を与えます。攻撃者は、クライアント側のチェックをバイパスする可能性があります。

40
tim

これをテストする最も簡単な方法は、送信専用アドレス(つまり、noreply-randomblue @ example.com)からそのアドレスにメールを送信することです。配送できない場合は無効です。

正規表現を使用してメールを解析することは、クライアント側でメールアドレスにタイプミスがある可能性があることを事前に知らせるためにおそらく最善の方法ですbefore登録します。

10
Philip Rowlands

あなたはsafe電子メールアドレスを持ちたいと言っています。これは、これらがアプリに組み込まれ、予測可能な出力が期待できることを意味すると思います。あなたのアプリを書いている開発者は、彼らの集団の頭に電子メールフィールドの中で何を期待するべきかについていくつかの考えを持っています、そしてあなたはそこで他に何も許可しない方がいいです。プログラマーが期待していないことは、あまり安全ではありません(恐ろしいRFCに従って有効であったとしても)。

したがって、開発者が電子メール関連のRFCにあまり興味がない場合は、 "RFC 5322の故意の違反"を使用することをお勧めします。 HTML5のW3C標準であり、非常に単純な正規表現に変換されます。

^[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])?)*$

ソース http://www.w3.org/TR/html5/forms.html#valid-e-mail-address

これがあまりにも緩い場合(開発者がそれらの奇妙なことを期待していないと思う場合は#$%&|など)、もう少し保護することをお勧めします。

^[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])?)+$

実際の人の住所の99.9%がこれらの表現の両方に一致すると思います。

8
kubanczyk

この種のことを心配することに時間を費やすことができます。なぜそんなに気にしてるの?

そのようなものとして実際に危険なアドレスはありません-それはあなたがそれで何をするか/あなたがそれを処理する方法であることが重要です。

安全でない方法で住所を処理した場合。文字列を連結してパラメーターを使用する代わりにsqlを作成すると、電子メールアドレスだけでなく、ユーザーが入力できるすべてのフィールドで問題が発生します。

簡単に言えば;それを提供する

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

または単に:

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

あなたはそれを許可する必要があります。これらの文字が何であるかは問題ではありません。

4
Matt Wilko

単一のフィルターや防御に頼るのではなく、階層化されたアプローチを使用する必要性を強調する対応は正しい方向に進んでいます。メールアドレスを検証するための「正しい」正規表現を書くことについては、たくさんの記事があります。実際には、いくつかのチェックを組み合わせる必要があり、正規表現に依存することはできません。

どのチェックが必要かは、それが何をしようとしているか、何をリスクから保護しようとしているかによって異なります。スパマーを特定しようとしているだけの場合は、コンテンツ、件名、発信元のメールサーバーも確認する必要があります。一方、登録プロセスでメールアドレスを確認する場合は、ドメインを確認したり、アドレスにメッセージを送信する確認プロセスを追加したりすることができます。

私のアドバイスは@MattWilkoに似ています。完璧な正規表現を導き出そうとすると、すぐに収益が減少します。式がより複雑になると、より多くの不正なアドレスが検出されますが、ほぼ確実に誤検知の数も増加します。重要なことは、適切なバランスを見つけることです。そのバランスは、ユースケースと保護しようとするリスクによって異なります。

0
Tim X