クライアントのウェブサイトをより安全にするために、ログインスクリプトを書き直したいと思っています。これに実装できるベストプラクティスを知りたい。パスワードで保護されたコントロールパネルは豊富にありますが、コードの記述、速度、セキュリティの点でベストプラクティスを暗示するものはほとんどありません。
PHPとMYSQLデータベースを使用します。
以前はmd5を使用していましたが、sha256またはsha512が(安全なハッシュおよびソルトと合わせて)優れていることがわかりました。
一部のログインスクリプトは、セッション全体またはユーザーエージェントでさえもIPアドレスを記録しますが、プロキシサーバーと互換性がないため、これを避けたいと思います。
また、PHP 5(最後に読んだのはPHP 4))でセッションを使用する際のベストプラクティスに少し遅れているので、これに関するいくつかのベストプラクティスは役立ちます。
ありがとう。
最善の考えは、ホイールを再発明しないことです。しかし、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]チェックボックスをオフにする必要があります)。
<span/>
。この場合、ブラウザはパスワードフィールドに入力できません(少なくともFirefoxはこれを実行できません)。そのため、ログオフしてから、ブラウザで入力された通常のフォームでログオンする必要があります。bcrypt
を使用してください。それ以外の場合は、他の種類の反復ハッシュを使用します。mysql_real_escape_string
などの関数を使用する必要がある方法でデータベースクエリを作成します。クエリの作成に文字列連結を使用しないでください。 準備され、パラメータ化されたクエリを使用します。すべてではないにしても、PHPのほとんどのDBドライバがサポートしています。それを行う方法を知っている、使用しているDBを使用してprepare
、bind
、およびexecute
の方法を学ぶのに少し時間をかけてください。それはonlySQLインジェクションから身を守る確実な方法PDOはこれをサポートしています。ソルト化された一方向ハッシュを使用します(できれば http://au2.php.net/manual/en/function.hash.php を使用してSHA512を使用)...その方法で、誰かがデータベースをハッキングした場合、たとえソルトを知っていても、パスワードを抽出することはできません(SHA512には間抜けになるRainbowテーブルがないと)。
HTTPSを使用します。
ユーザー名/パスワードの確認は、登録時にユーザーにメールで返信しないでください。
「remember me」のCookieを許可する場合-管理機能とプロファイル編集機能にアクセスするための追加のログインを追加します。
ユーザーがパスワードを間違えた場合でも、パスワードを間違えたとは言わないでください(常に「ユーザー名またはパスワードが間違っていた」と言います)。これにより、有効なユーザー名の手がかりが少なくなります。
ログインとスクリーンネームを比較して実装してください。そうすることで、ユーザーリストにログイン名を表示するユーザーが減ります。
ここに少しアドバイスがあります:盗難を防ぐためにJSでCookieにアクセスできないようにしてください (Cookieの保護:HttpOnly Jeff Atwoodによる記事を参照)
...巧妙な構造により、不正なURLは消毒剤を通り過ぎてしまいました。最終的にレンダリングされたコードは、ブラウザーで表示されるときに、そのリモートサーバーからスクリプトを読み込んで実行します。
...このスクリプトが挿入されたユーザープロフィールページをロードした人が、意図せずにブラウザのCookieを悪意のあるリモートサーバーに送信しただけです
私たちがすでに確立しているように、誰かが特定のWebサイトのブラウザCookieを取得すると、基本的にそこにあなたのアイデンティティの王国への鍵があります...