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


27

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

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

以前はmd5を使用していましたが、sha256またはsha512の方が(安全なハッシュとソルトと共に)優れていることがわかります。

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

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

ありがとう。


1
codereview.SEでスクリプトを投げます!
クリス

@Chris CodeReviewは、コードの明快さなどを支援します。あなたは間違いなくセキュリティのために彼らに行くことになっていない。どちらかといえば、彼らはほとんど常に「あなた自身のものを転がさない」ことを思い出させるでしょう。
Alternatex

回答:


21

最良の考えは、車輪を再発明しないことです。しかし、PHPの世界では、それを既に実現している高品質のコンポーネントを見つけることは難しいかもしれません(フレームワークがそのようなことを実装し、その実装が既にテストされ、しっかりしており、コードレビューなどが行われていると確信しています) )

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

セキュリティ関連の提案

  • 可能であれば、PBKDF2またはBcryptを使用します。これで完了です。

    理由:両方のアルゴリズムは、ハッシュプロセスをarbitrarily意的に遅くすることができます。これは、パスワードをハッシュするときにまさに必要なものです(より簡単な代替手段は、ブルートフォースを容易にすることを意味します)。理想的には、同じハードウェア上で時間の経過とともにプロセスが徐々に遅くなるようにパラメーターを調整し、新しい高速のハードウェアがリリースされるようにする必要があります。

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

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

  • PHP 5.5.0以降では、とを使用password_hashpassword_verifyます。

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

  • 総当たり攻撃から身を守ります。ユーザーが0.01秒前に別の間違ったパスワードを既に送信したときに、間違ったパスワードを送信した場合、それをブロックするのは正当な理由です。人間が速く入力することができますが、彼らはおそらくすることができないという速いです。

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

    根拠:パスワードが安全でない方法でハッシュ化される場合、ブルートフォースは非常に効果的です。パスワードが安全に保存されている場合、ブルートフォースは依然としてサーバーのリソースとネットワーク帯域幅を浪費し、正当なユーザーのパフォーマンスを低下させます。ブルートフォースの検出は、開発も正しくも簡単ではありませんが、ごく小さなシステムにとっては、まったく価値があります。

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

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

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

  • ユーザーが要求しない限り、Cookie内のユーザー資格情報を記憶しないでください(人的エラーを避けるために、既定で[記憶する]チェックボックスをオフにする必要があります)。

使いやすさの提案

  • ほとんどのブラウザがすでにこの機能である場合でも、必要に応じてユーザーにパスワードを思い出させます
  • ユーザー名とパスワードを要求する代わりに、ユーザーがパスワードのみを要求される場合は、Googleのアプローチを使用しないでください<span/>。ユーザー名はに既に表示されています。この場合、ブラウザはパスワードフィールドに入力できません(少なくともFirefoxでは実行できません)。そのため、強制的にログオフしてから、ブラウザで入力された通常のフォームでログオンします。
  • ログオンにJavaScript対応のポップアップを使用しないでください。それはブラウザのパスワードを記憶する機能を破壊します(そして、すべての場合においてはうんざりします)。
  • ユーザーが入力してみましょう彼女のユーザー名または彼女のメールアドレスのどちらかを。登録するときに、入力したいユーザー名がすでに使用されている場合があるため、新しいユーザー名を作成する必要があります。2時間以内にこの名前を忘れる可能性があります。
  • ログオンフォームの近くに「パスワードを忘れた」機能へのリンクを常に保持してください。ユーザーがログオンに失敗した場合にのみ表示しないでください。パスワードをまったく覚えていないユーザーは、「パスワードを忘れた」リンクを表示するために間違ったパスワードを送信する必要があることを知りません。
  • post-itでセキュリティを使用しないでください。
  • パスワードをより弱くするために、パスワードに関連するバカなルールを発明しないでください。例:「パスワードは小文字で始める必要があります。」; 「パスワードにスペースを含めることはできません。」

bcryptに出くわすことはありません。それを推奨する理由は何ですか?なぜmd5 / sha1ではありませんか?残りの提案をありがとう!
baritoneuk

推論は簡単ですbcrypt。高度な資格を持つ人々によって行われます。また、テストやレビューなども行われています。したがって、同じことを自分で実装する理由はありません。それは、あなたのウェブサイト用に独自の暗号アルゴリズムを作成するようなものです。* "なぜMD5 / SHA1?":例を参照en.wikipedia.org/wiki/MD5#Security
Arseni Mourzenko

5
bcryptは低速であり、前述のように専門家によって実装されています。md5は暗号化ではなくハッシュアルゴリズムであり、まったく同じものではありません。ファイルを高速にハッシュするのは良いことです。ここではmd5を使用します。パスワードのハッシュはそれほど高速である必要はありません。bcryptはここで役立ちます。理由は、これは、暗号アルゴリズムが「遅い」場合、ブルートフォースがより難しくなるということです。
クリス

2
@baritoneuk:最小はクールです。しかし、最大長、英数字以外の文字などの制限があるサイトにいくつアクセスしたかは数えられません。とにかくパスワードをハッシュしようとすると困惑します。 、彼らはそれをデータベースに平文で保存しているだけです。
Carson63000

1
@ブライアンオルティス:常にではない。制限を設定することをお勧めします。実行しない場合、アプリケーションが任意の長さで機能するかどうかをテストしますか?どうやって?テストしない場合、それが機能しているかどうかをどのように確認できますか?代わりに、100などの妥当な値に制限を設定する場合、100文字のパスワードを簡単にテストできます。
アルセニムルゼンコ

6
  1. サイトはHTTPS使用する必要があります。ログインページを表示したり、暗号化されていない接続からのログインを受け入れたりしないでください。
  2. あなたのクッキーは、HTTP-のみに制限されなければならないあなたはHTTPSを使用する場合の接続を確保するために制限されます。
  3. ログインプロセスには2秒以上かかります(2秒が長すぎると思われる場合は1秒)。パスワードを保存および検証するときは安全なハッシュを使用し、推測しにくいソルトを使用します。bcrypt可能であれば使用してください。それ以外の場合は、他の種類の反復ハッシュを使用します。
  4. などの関数の使用を必要とする方法でデータベースクエリを作成しないくださいmysql_real_escape_string。クエリの作成に文字列連結を使用しないでください。準備され、パラメータ化されたクエリを使用します。すべてではないにしても、ほとんどのPHP用DBドライバーがサポートしています。方法がわからない場合は、使用するDBの使い方を学習しprepare、使用しているDBを使用してください。それはだだけで、SQLインジェクションから身を守るために確実な方法。PDOはこれをサポートします。bindexecute
  5. ユーザーがメールに使用するのと同じパスワードを使用しないように奨励します。サイトが危険にさらされ、両方の場所で同じパスワードを使用している場合、だれかがメールをハイジャックできることを思い出させてください。

パブリックWiFiネットワークを介したトラフィックが増加しているため、HTTPSの場合は+1。しかし、ポイント3には同意しません。ユーザーの観点からは、2秒は長すぎます。0.5秒 特に他のブルートフォース技術が使用されている場合は特に問題ありません。
アルセニムルゼンコ

ポイント番号#4で混乱しています。mysql_real_escape_stringを使用してデータをエスケープする規則をどのようにエスケープしますか?すべてのユーザーが送信したデータは信頼され、それに応じてフィルタリングされるべきではありません。
クリス

@chrisw:はい、すべてのユーザー入力は悪意のあるものとして処理する必要があります。ただし、パラメーター化されたクエリを使用する場合、SQL注入を停止する最善の方法は禁止です。準備され、パラメータ化されたクエリを使用していない場合、SQLインジェクションに対して脆弱です。mysql_real_escape_string偽のセキュリティです-それは保証ではありません。パラメータ化されたクエリは。
greyfade

さらに読んで、今同意します。関数:mysql_real_escape_stringはほとんどの部分で一般に安全です。私はそれを大きな責任とは思わないでしょうが、準備されたステートメントを使用する方がはるかに効率的であることがわかります。
クリス

1
PDOを使用できます。
フェリックスG

1

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

HTTPSを使用します。

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

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

ユーザーがパスワードを間違えた場合、パスワードを間違えたと言ってはいけません(常に「ユーザー名またはパスワードを間違えた」と言います)-そうすれば、有効なユーザー名の手がかりが少なくなります。

ログインとスクリーン名を対比して試してみてください-このようにすると、ユーザーリストにログイン名を表示するユーザーが少なくなります。


電子メールでプレーンテキストの電子メールを送信しないことに関するビットに完全に同意します。Webサイトがこれを行う回数を失いました。すべてのサイトに1つのパスワードを持っている場合(幸いなことに私は持っていません)、すべてのWebサイトが危険にさらされる可能性があります。このようなWebサイトでは、おそらくパスワードもプレーンテキストで保存されます。ため息
baritoneuk

1
  • MD5またはSHA1ハッシュアルゴリズムを使用しないでください。常にSHA512のような新しいものに固執する
  • 強力でランダムに生成されたソルトを常に使用する
  • 「パスワードを忘れた」場合でも、ユーザーにパスワードをメールで送信しないでください
  • mysql_ *関数を使用しないでください。彼らは長い間減価償却されています。PDOに固執する
  • セッションまたはCookieにパスワードを保存しない

0

ちょっとしたアドバイスがあります。盗難を防ぐためにJSでCookieにアクセスできないようにしてください。ジェフアトウッドによるCookieの保護:HttpOnlyの記事をご覧ください。

...巧妙な構成により、不正な形式のURLがサニタイザーをすり抜けます。ブラウザで表示される最終レンダリングコードは、そのリモートサーバーからスクリプトをロードして実行します。

...このスクリプトが挿入されたユーザープロファイルページを読み込むユーザーは、ブラウザーのCookieを意図せずに悪意のあるリモートサーバーに送信します。

すでに確立しているように、誰かが特定のWebサイトのブラウザCookieを取得すると、そのIDの王国へのキーを本質的に持っています...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.