web-dev-qa-db-ja.com

Is_email()関数に渡す前にEメールアドレスをサニタイズするべきですか?

私は is_email() を使用して、ユーザー提供の電子メールアドレスが有効かどうかを確認しています。例えば:

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

私の知る限りでは、この関数でデータベースに情報を書き込むものはありません。関数に渡す前に$emailをサニタイズするべきですか?

13
henrywright

Tracの is_email() の機能性を見ると、それは単なる文字列テストなので、あなたがサナタイズする必要はないようです。この関数がtrueを返す場合は、データベースに送信する前にサニタイズする必要はないと言っています。

5
Howdy_McGee

WordPressとPHPコア

is_email() 関数 出典 は典型的なWordPressの実装であり、 RFC 6531 が許すものでは完全には動作しません。 1つの理由は、デフォルトのPHP FILTER_VALIDATE_EMAILfilter_var()の定数は、 The Internet Engineering Task Force(IETF®) のガイドラインに従って何かを検証するのには向いていないことです。

規格

要点はRFC 6531"ASCIIの範囲を超えたUnicode文字"を許可するということです。すなわち、それらは(ローカル部分のために - @の前に):

  • 大文字と小文字の英字(a - z、A - Z)(ASCII:65 - 90、97 - 122)
  • 0から9までの数字(ASCII:48–57)
  • これらの特殊文字:! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • 文字.(ドット、ピリオド、フルストップ)(ASCII:46)は、それが最初の文字または最後の文字ではないこと、および連続して表示されないことを条件とします(例:[email protected]は許可されません)。
  • 特殊文字は制限付きで許可されています。彼らです:
    • スペースと"(),:;<>@[\](ASCII:32、34、40、41、44、58、59、60、62、64、91–93)
    • 特殊文字の制限は、引用符で囲まれている場合にのみ使用しなければならないこと、およびそのうちの2つ(バックスラッシュ\と引用符 "(ASCII:92、34))の前にバックスラッシュ\(例:"\\")も必要です。 "\"").
  • ローカル部分の両端に括弧を付けてコメントを書くことができます。例えばjohn.smith(comment)@example.com(comment)[email protected]はどちらも"[email protected]"と同等ですが、john.(comment)[email protected]は無効です。
  • UTF-8としてエンコードされたU+007Fより上の国際文字はRFC 6531によって許可されていますが、ローカル部分を割り当てるときに使用する文字をメールシステムが制限するかもしれません。

そしてグローバル/ドメイン部分のために:

電子メールアドレスのドメイン名部分は、厳密なガイドラインに従う必要があります。それは、文字、数字、ハイフン、およびドットで構成されるホスト名の要件に一致する必要があります。さらに、ドメイン部分は、jsmith@[192.168.2.1]jsmith@[IPv6:2001:db8::1]のように角括弧で囲まれたIPアドレスリテラルとすることができます[…]

出典:ウィキペディア

何が有効ですか?

これにより、次のような奇妙だが有効な電子メールアドレスが作成される可能性があります。

  • [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

出典:php.net /作者[email protected] - この記事の作者により修正された例

限界

ローカルおよびドメイン長の制限もあります。

Eメールアドレスのフォーマットはlocal-part@domainです。ここで、local-partは最大64文字ドメイン名は最大253文字です。ただし、最大256文字の長さ順方向パスまたは逆方向パスの]は、電子メールアドレス全体を254文字以下に制限します。[2]正式な定義はRFC 5322(セクション3.2.3と3.4.1)とRFC 5321にあります - より読みやすい形式は情報のRFC 3696 [3]と関連する正誤表で与えられます。

出典:ウィキペディア

WordPressの制限

そしてこれがWordPressがチェックするものです。

  • Eメールの最小長をテストします。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
  • ドメインが少なくとも2つのサブルーチンを持っていると仮定してください:$subs = explode( '.', $domain );そしてそれから
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

出典:WPコアv4.0

フィルタとカスタム検証

上記のすべてのケースでis_email()がfalseを返します。結果はフィルタ可能(コールバックをアタッチ可能)であり、フィルタは3つの引数を持ちます。最後の引数がその理由です。例:

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

つまり、特定のチェックによって返された結果を上書きすることができます。

これにより、ウムラウトドメイン、TLDのみのドメイン部分などを許可するなどの特別なチェックを追加できます。

結論

WordPressはほとんどの場合安全ですが、メールサーバーは実際にはRFCに準拠している必要があるため、より制限的です。すべてのメールサーバーがRF 6531のガイドラインに準拠しているわけではないことに注意してください。

編集する

面白い副作用:~/wp-includes/formattingの内部には、is_email()sanitize_email()の2つの関連する関数があります。それらは実質的に同じ関数です。他の人が提供するフィルタへのコールバックとして1つを追加するのではなく、あるものから別のものに関数の内容をコピーすることが賢明であると誰かが判断したのか、私にはわかりません。 As is_email() v0.71以降 および sanitize_email() v1.5以降 同じです、私は個人的にあなたがきれいな文字列を取得するように後で使用します。 is_email()は、RFCに準拠していないとさえ述べています。

18
kaiser

すべてのものを消毒する!

基本的なセキュリティ規則の1つは、ユーザーからの入力を決して信頼しないことです。一般的に、私はis_email()や他の特定の関数の実装、あるいはその関数が私が与えたものに対して危険なことをしているかどうかを気にしません。実装はいつか変わるでしょう。知るか。私はそれが妥協されることができると仮定しなければなりません。仮定は 常に ユーザーの入力は積極的に敵対的であり、最終的にはデータベースに向けられたものに対しては二重になり、ユーザー入力のあらゆる部分をサニタイズしてから何らかの機能に渡すというものです。これはただの良い、一般的な安全衛生です。

2
JesseM