web-dev-qa-db-ja.com

PHPログインスクリプトで採用すべきベストプラクティスは何ですか?

クライアントのウェブサイトをより安全にするために、ログインスクリプトを書き直したいと思っています。これに実装できるベストプラクティスを知りたい。パスワードで保護されたコントロールパネルは豊富にありますが、コードの記述、速度、セキュリティの点でベストプラクティスを暗示するものはほとんどありません。

PHPとMYSQLデータベースを使用します。

以前はmd5を使用していましたが、sha256またはsha512が(安全なハッシュおよびソルトと合わせて)優れていることがわかりました。

一部のログインスクリプトは、セッション全体またはユーザーエージェントでさえもIPアドレスを記録しますが、プロキシサーバーと互換性がないため、これを避けたいと思います。

また、PHP 5(最後に読んだのはPHP 4))でセッションを使用する際のベストプラクティスに少し遅れているので、これに関するいくつかのベストプラクティスは役立ちます。

ありがとう。

27
baritoneuk

最善の考えは、ホイールを再発明しないことです。しかし、PHP=世界では、すでにそれを実行する高品質のコンポーネントを見つけるのは難しいかもしれません(フレームワークがそのようなことを実装し、その実装がすでにテストされていると確信しているとしても) 、堅実、コードレビュー済みなど)

なんらかの理由でフレームワークを使用できない場合は、いくつかの提案があります。

セキュリティ関連の提案

  • 可能な場合はPBKDF2またはBcryptを使用。そのために行われます。

    理論的根拠:両方のアルゴリズムにより、ハッシュプロセスが任意に遅くなる可能性があります。これは、パスワードをハッシュするときにまさに必要なことです(より高速な代替案では、総当たりが容易になります)。理想的には、新しいハードウェアがリリースされると同時に、同じハードウェアでプロセスが徐々に遅くなるようにパラメーターを調整する必要があります。

  • できない場合は、少なくともMD5/SHA1は使用しないでください。決して。忘れてください。たとえば、代わりにSHA512を使用します。塩も使ってください。

    根拠:MD5とSHA1は速すぎます。攻撃者がハッシュを含むデータベースにアクセスでき、(特に)強力なマシンを持っている場合、パスワードの総当たりはすばやく簡単です。ソルトがない場合、攻撃者が実際のパスワードを見つける可能性が高くなります(パスワードが別の場所で再利用された場合、さらに害を及ぼす可能性があります)。

  • PHP 5.5.0以降では password_hash および password_verify

    理論的根拠:フレームワークによって提供される関数の呼び出しは簡単なので、間違いを犯すリスクが軽減されます。これらの2つの関数を使用すると、ハッシュなどの異なるパラメーターについて考える必要がなくなります。最初の関数はsingle文字列を返し、データベースに保存できます。 2番目の関数は、パスワード検証にこの文字列を使用します。

  • ブルートフォースから身を守る。 0.01秒前にユーザーが別の間違ったパスワードを既に送信したときにユーザーが間違ったパスワードを送信した場合、それをブロックするのは良い理由です。人間は速くタイプすることができますが、おそらくそれ速くすることはできません。

    別の保護は、1時間あたりの障害制限を設定することです。ユーザーが1時間に1秒あたり1つのパスワードで3600個の間違ったパスワードを送信した場合、これが正当なユーザーであるとは信じられません。

    根拠:パスワードが安全でない方法でハッシュされている場合、ブルートフォースは非常に効果的です。パスワードが安全に保存されている場合でも、ブルートフォースによってサーバーのリソースとネットワーク帯域幅が無駄になり、正当なユーザーのパフォーマンスが低下します。ブルートフォースの検出は、開発と修正が容易ではありませんが、小さなシステム以外では、それだけの価値があります。

  • 4週間ごとにパスワードを変更するようユーザーに要求しないでください。これは非常に煩わしく、減少ポストイットベースのセキュリティを促進するため、セキュリティが低下します。

    理論的根拠:n週ごとにパスワードを強制的に変更することは、システムをブルートフォースから保護するという考えは間違っています。ブルートフォース攻撃は通常、数秒、数分、数時間、または数日で成功するため、毎月のパスワードの変更は重要ではありません。一方、ユーザーはパスワードを覚えるのが苦手です。さらに、それらを変更する必要がある場合は、非常に単純なパスワードを使用するか、ポストイットにパスワードを書き留めます。

  • 毎回すべてを監査します。ログオンを保存しますが、監査ログにはパスワードを保存しません。 監査ログを変更できないことを確認してください(つまり、最後にデータを追加できますが、既存のデータは変更できません)。監査ログが定期的にバックアップされることを確認してください。理想的には、ログはアクセスが非常に制限された専用サーバーに保存する必要があります。別のサーバーがハッキングされた場合、攻撃者はログを消去して自分の存在(および攻撃中にたどった経路)を隠すことはできません。

  • ユーザーが要求しない限り、ユーザー資格情報をCookieに記憶しないでください(人為的エラーを回避するために、デフォルトで[Remember me]チェックボックスをオフにする必要があります)。

使いやすさの提案

  • ユーザーにパスワードを記憶させるほとんどのブラウザがすでにこの機能を備えている場合でも、必要に応じて。
  • ユーザー名とパスワードを要求する代わりに、Googleのアプローチを使用しないでください。ユーザーはパスワードのみを要求される場合がありますであり、ユーザー名は<span/>。この場合、ブラウザはパスワードフィールドに入力できません(少なくともFirefoxはこれを実行できません)。そのため、ログオフしてから、ブラウザで入力された通常のフォームでログオンする必要があります。
  • ログオンにJavaScript対応ポップアップを使用しないでください。それはブラウザのパスワードを記憶する機能を壊します(そしてすべての場合に吸います)。
  • ユーザーにユーザー名またはメールアドレスを入力させます。登録したいのですが、入力したいユーザー名が既に使用されていることがあるので、新たに発明する必要があります。私はこの名前を2時間で忘れる可能性があります。
  • 常に[パスワードをお忘れの方]へのリンク機能をログオンフォームの近くに置いてください。ユーザーがログオンに失敗した場合にのみ表示しないでください。自分のパスワードをまったく覚えていないユーザーは、「パスワードを忘れた」リンクを表示するために間違ったパスワードを送信する必要があることを知りません。
  • post-itによるセキュリティ は使用しないでください。
  • 発明しないでくださいパスワードを弱くするためにパスワードに関連する愚かなルール。例:「パスワードは小文字で始める必要があります。」; 「パスワードにスペースを含めることはできません。」
21
  1. あなたのサイトは HTTPSを使用します。 ログインページを表示したり、暗号化されていない接続からのログインを受け入れたりすることは決してありません。
  2. CookieはHTTPのみに制限する必要があり、HTTPSを使用する場合は安全な接続に制限する必要があります。
  3. ログインプロセスは2秒以上かかるはずです(2秒が長すぎると思われる場合は1)。 安全なハッシュを使用 パスワードを保存および検証するときは、推測しにくいソルトを使用します。可能であればbcryptを使用してください。それ以外の場合は、他の種類の反復ハッシュを使用します。
  4. 決してevermysql_real_escape_stringなどの関数を使用する必要がある方法でデータベースクエリを作成します。クエリの作成に文字列連結を使用しないでください。 準備され、パラメータ化されたクエリを使用します。すべてではないにしても、PHPのほとんどのDBドライバがサポートしています。それを行う方法を知っている、使用しているDBを使用してpreparebind、およびexecuteの方法を学ぶのに少し時間をかけてください。それはonlySQLインジェクションから身を守る確実な方法PDOはこれをサポートしています。
  5. ユーザーに、メールに使用しているのと同じパスワードを使用しないように勧めます。サイトが危険にさらされており、両方の場所で同じパスワードを使用している場合、誰かがメールをハイジャックする可能性があることを伝えます。
6
greyfade
  • MD5またはSHA1ハッシュアルゴリズムを使用しないでください。常にSHA512のような新しいものに固執する
  • 常にランダムに生成された強い塩を使用する
  • 「パスワードを忘れた」場合でも、ユーザーにパスワードを電子メールで送信しないでください
  • Mysql_ *関数を使用しないでください。彼らは長い間減価償却されています。 PDOに固執する
  • セッションまたはCookieにパスワードを保存しないでください
1
Robin Thomas

ソルト化された一方向ハッシュを使用します(できれば http://au2.php.net/manual/en/function.hash.php を使用してSHA512を使用)...その方法で、誰かがデータベースをハッキングした場合、たとえソルトを知っていても、パスワードを抽出することはできません(SHA512には間抜けになるRainbowテーブルがないと)。

HTTPSを使用します。

ユーザー名/パスワードの確認は、登録時にユーザーにメールで返信しないでください。

「remember me」のCookieを許可する場合-管理機能とプロファイル編集機能にアクセスするための追加のログインを追加します。

ユーザーがパスワードを間違えた場合でも、パスワードを間違えたとは言わないでください(常に「ユーザー名またはパスワードが間違っていた」と言います)。これにより、有効なユーザー名の手がかりが少なくなります。

ログインとスクリーンネームを比較して実装してください。そうすることで、ユーザーリストにログイン名を表示するユーザーが減ります。

1
HorusKol

ここに少しアドバイスがあります:盗難を防ぐためにJSでCookieにアクセスできないようにしてください (Cookieの保護:HttpOnly Jeff Atwoodによる記事を参照)

...巧妙な構造により、不正なURLは消毒剤を通り過ぎてしまいました。最終的にレンダリングされたコードは、ブラウザーで表示されるときに、そのリモートサーバーからスクリプトを読み込んで実行します。

...このスクリプトが挿入されたユーザープロフィールページをロードした人が、意図せずにブラウザのCookieを悪意のあるリモートサーバーに送信しただけです

私たちがすでに確立しているように、誰かが特定のWebサイトのブラウザCookieを取得すると、基本的にそこにあなたのアイデンティティの王国への鍵があります...

0
James