web-dev-qa-db-ja.com

パスワードデータベースの安全な実装

免責事項私はセキュリティの専門家ではなく、プログラマーが最善を尽くそうとしています。さらに、これはこのコミュニティへの私の最初の投稿なので、この質問が広すぎると申し訳ありません。

状況私のローカルネットワーク(専門のITチームによって管理および保護されている)には、データロガー、PIDコントローラーなどを制御するために使用されるページを提供するシンプルなWebサーバーを実行する多くのデバイスがあります。これらのWebページには現在、認証の形式はまったくありません。悪意のある人物がネットワークに危害を加えた場合、これは大きな問題になります。

My Goalは、サーバーが実行しているアプリにログインページを追加して、これらのWebページに認証を追加することです。 (おそらく関連性があり、私はPythonを使用してサーバーを実行しています。)

私の実装私は以下のことを行う概念実証設計を持っています:

  • ユーザーは登録ページでユーザー名とパスワードの入力を求められます
  • サーバーはSHA256を使用してパスワードをハッシュし、同じ長さのハッシュを作成します
  • ランダムなソルトは、適切な作業係数を使用して生成されます。
  • ハッシュされたパスワードは、今度はソルトを使用して再度ハッシュされます。 (ソルト生成とハッシュはpythonのbcryptを使用します)
  • ユーザー名、作業係数、ソルト、ハッシュはパスワードデータベースに保存されます。
  • ユーザーがログインを試みると、入力されたパスワードは同じ方法でハッシュされ、データベースのレコードと比較されます。 (比較に使用されるソルトは、入力されたユーザー名をキーとして使用して、パスワードデータベースからフェッチされます。)
  • ハッシュが一致すると、制限されたWebページへのアクセスを許可するCookieがユーザーに与えられます。

(Webページとサーバー間のすべての通信はPOSTリクエストを使用していることに注意してください。)

質問と懸念

  • ハッシュ、作業係数、ソルトを同じデータベースに保存することは悪い習慣のようです。
  • このハッシュ方法では、(合理的に)自分自身を含め、誰もユーザーのパスワードを特定できないようになっていますか?
  • 現在、すべてがhttpを使用しています。すべてのアクセスがローカルネットワーク内にある場合、httpsは必要ですか?
  • Cookieを使用すると、ユーザーが正常にログインしたことを確認できますか?
26
Rekamanon

認証の現在の一般的なベストプラクティスは NIST SP 800-63-3デジタルIDガイドライン標準 にあり、特に SP-63B認証とライフサイクル管理

これらのNIST標準は、開発者にとって読みやすいものであり、何をすべきかを指示するだけでなく、特定のことをしたい理由についても説明します。 (NIST標準よりも詳細な情報が必要な場合は、喜んでお手伝いします。)

それでは、現在の認証システムを調べて、懸念事項に対処しましょう。

ユーザーは登録ページでユーザー名とパスワードの入力を求められます

登録ページ?

これはおそらくタイプミスでログインページを意味しますが、ネットワーク上の誰でもアクセスできる登録ページがある場合は、別個の認可システムを明示的に定義する必要があります。たとえば、誰でも任意のオンラインストアでアカウントを登録できますが、このアカウントでは、管理者が製品の価格を変更できるサイトの一部にアクセスできません。

サーバーはSHA256を使用してパスワードをハッシュし、同じ長さのハッシュを作成します

特にbcryptを使用しているため、この手順によってセキュリティが強化されたり、システムパフォーマンスが意味のある方法で向上したりすることはありません。bcryptを使用すると、最初の72文字を超えるとパスワードの一部が破棄されます。

可能性は低いですが、このステップはエントロピーを減らすことができます。エントロピーの減少は、大まかな計画では重要ではなく、ユーザーはすでにランダムに生成された長いパスワードを使用している必要がありますが、これはセキュリティを向上させない追加の手順であるため、省略することをお勧めします。

ランダムなソルトは、適切な作業係数を使用して生成されます。

最初はこのステップを見て混乱していたことを認めます。これが自動車のメンテナンスに関するものであれば、「合理的なオクタン価の合成油を追加する」のと同じくらい理にかなっています。ただし、コメントで、使用されている特定のbcryptライブラリは PyPIがホストするbcryptライブラリ であることが明らかになりました。

私はソースコードを見つけることができません(そして、スコープを区切るために空白を使用する言語にアレルギーがあります)が、ドキュメントに基づいて、bcryptのパラメーターを生成するためのライブラリーの関数呼び出しはbcrypt.gensalt(workfactor)このメソッド自体は、作業係数をパラメーターとして受け取ります...車のメンテナンスのメタファーを拡張すると、vehicle.refuel(viscosity)、またはvehicle.changeoil(octane)という名前の関数があるかのようになります。

認証と暗号化の専門用語でのソルトは、プレーンテキストに追加されるランダムな値であり、暗号化ハッシュ関数またはキー導出関数の出力を事前に計算することを不可能にします。塩自体は秘密ではありません。その唯一の強みは、事前に知られていないことです。

塩の値は、その長さで測定され、そのエントロピーとも呼ばれます。 (暗号化におけるエントロピーは微妙なトピックであり、長さだけではありませんが、ソルトを作成するreasonableライブラリの場合、ソルトが長いほど、エントロピーが大きくなります。 )

一方、作業要素は、このbcrypt KDFなどのキーストレッチアルゴリズムに固有の専門用語です。作業係数は、CPU(またはGPU、FPGA、またはASIC))が実行する必要がある作業量を定義します。主な機能は、出力の計算に時間がかかることです、バイパス、推測、または無視できないステップを使用します。これは直観に反するように思えるかもしれません。アプリケーションをできるだけ速く実行したいですか?

まあ、一般的なリスクは、パスワードのデータベースが漏洩することです。一流の小売業者は常にパスワードを漏らしており、一流の小売業者のようにアプリケーションのセキュリティ保護に費やす何百万ドルもないので、パスワードのデータベースも最終的に漏らされる可能性があると想定します。

ここでのトレードオフは、ログインするときに、ユーザーがさらに1秒待つ必要があることです。攻撃者がパスワードを解読するとき、攻撃者がタスクに入力したCPUごとに1秒あたり1つのパスワードしか推測できません。 (意欲的な攻撃者はいくつかの近道をとることができますが、キーストレッチアルゴリズムの代わりに単一ラウンドのSHA256を使用している場合、1秒あたり10推測でも1秒あたり数十億推測よりはるかに優れています。

したがって、塩と仕事係数はどちらも、互いに何の関係もない重要なパラメータです。コンセプトへの最初の露出が非常に不十分な名前の関数を介して行われたことを残念に思います。

ハッシュされたパスワードは、今度はソルトを使用して再度ハッシュされます。 (ソルト生成とハッシュはpythonのbcryptを使用します)

マイナーニッピックですが、これは私が徹底しているためです。多くの人がハッシュと呼んでも、bcryptの結果はハッシュではありません。これを続ければ、ここの誰もがあなたが話していることを知っています。ハッシュ。結果はストレッチされたパスワードまたは派生キーです。

ユーザー名、作業係数、ソルト、ハッシュはパスワードデータベースに保存されます。

結果が次のようなものであれば、作業係数、ソルト、および派生キーがすべて揃っています。

$2a$08$0SN/h83Gt1jZMR6924.Kd.HaK3MyTDt/W8FCjUOtbY3Pmres5rsma

2aはアルゴリズムです(ユニコードをサポートするbcrypt)。

08は作業係数です。

次の22文字の0SN/h83Gt1jZMR6924.Kd.はソルトです。

そして、残りは派生キーです。

Bcryptライブラリとは異なるものを取得している場合は、別のライブラリを見つけてください。

ユーザーがログインを試みると、入力されたパスワードは同じ方法でハッシュされ、データベースのレコードと比較されます。 (比較に使用されるソルトは、入力されたユーザー名をキーとして使用して、パスワードデータベースからフェッチされます。)

すごい。ただし、使用しているライブラリはすでに重い作業を行っているため、ライブラリを最大限に使用してください。 bcrypt.checkpw関数は、作業係数、ソルト、および派生キーを引き出します。次に、KDFを実行して結果を比較します。

このライブラリ関数を使用すると、将来的にデフォルトの作業係数を変更する場合、古い派生キーを処理するための個別のコードをbcrypt.checkpwとして持つ必要がなくなります。自分で希望する仕事の要素を把握することができます。

ハッシュが一致すると、制限されたWebページへのアクセスを許可するCookieがユーザーに与えられます。

これは一見すると素晴らしいように思えますが、Cookie自体に認証が含まれていないことを確認してください。ランダムに生成された文字列(セッションID)が含まれている必要があり、サイトにアクセスするときに、サーバーはそのセッションIDを調べ、独自のリソースをチェックして、そのセッションIDが適切に承認されているかどうかを確認する必要があります。しばらくして、セッションIDもクリーンアップします。

CookieにセッションIDではなく「is_authorized = true」が含まれ、サーバーが自身のリソースを再確認する場合、ユーザーは自分の承認Cookieを作成するだけで認証を行う必要はありません。


懸念事項:

ハッシュ、作業係数、ソルトを同じデータベースに保存することは悪い習慣のようです。

Saltとworkの要素はどのような意味でも機密ではありませんが、パスワードの検証に必要です。せいぜい、塩を隠そうとする試みは、セキュリティによる不明瞭さをもたらします。これは、いかなる種類のセキュリティでもありません。作業キーとソルトを派生キーと一緒に保存して、頭痛を軽減することもできます。それらを分割しても、攻撃者がアクセスするのを防ぐことはできないからです。

このハッシュ方法では、(合理的に)自分自身を含め、誰もユーザーのパスワードを特定できないようになっていますか?

あなたのウェブ開発者としての責任は?はい。

そして、合理的に誰もパスワードを特定できないことを保証するかどうか尋ねてくれてありがとうオフライン攻撃では推測できますが、bcryptなどのキーストレッチアルゴリズムを使用すると、リークされたデータベースに対するオフライン攻撃の最悪のシナリオでも、攻撃者を大幅に妨害できます。

あなたがもっと上手くできる唯一のことは、2faを追加し、すべてのサイトに固有の24文字以上の真にランダムなパスワードを持つパスワードマネージャーをユーザーに使用させることです。

パスワードのリセットは、この2番目の要素にonlyを依存すべきではないことに注意してください。 NISTガイドラインに従って、それはそもそもアカウントの設定で使用されたものと同じ識別要素に依存する必要があります(そして、アプリケーションが知っている限り多くのユーザー通信チャネルでできるだけ多くのノイズを作ります)および可能な場合、少なくとも1つの追加の要素を利用します。

ほとんどのウェブアプリケーションでは、これはアカウント登録中に使用されたアカウントへのメール([〜#〜]ではない[〜#〜]へのテキストメッセージ)携帯電話、またはセキュリティの質問自体。ただし、これらは追加の要素になる可能性がありますメールが送信されます)。内部ビジネスアプリケーションの場合、これはユーザーがsysopsチーム/ヘルプデスクに電話をかける必要があることを意味します(より現実的には、開発者のデスクに立ち寄る必要があります)。

現在、すべてがhttpを使用しています。すべてのアクセスがローカルネットワーク内にある場合、httpsは必要ですか?

ローカルネットワークをある程度信頼する必要があります。ただし、HTTPSを追加しても問題はありません。心配な場合は、HTTPSを追加してください。 (この質問をしたという事実は、はい、心配しているということです。そのため、はい、HTTPSを追加する必要があります。)

HTTPSを追加することは、セキュリティ以外の理由からも良い考えです。Webサーバー(およびブラウザー)は、HTTPS接続でのみHTTP/2を使用します(可能な場合)。これにより、サイトを著しく高速化できます。 HTTP/2機能を備えている可能性が低いPythonスクリプトベースのWebサーバーを使用しているため、これは当てはまりませんが、「単なる」セキュリティ以上の理由で侵入するのは良い習慣です。 (セキュリティは私の意見では十分すぎるほどの正当化ですが、追加の説得力を必要とするマネージャーがいます。)

Cookieを使用すると、ユーザーが正常にログインしたことを確認できますか?

そのCookieに認証情報ではなくセッションIDが含まれている場合、そのセッションIDはランダムであり、サーバーはセッションIDを検証します。これは、あらゆる種類のユーザーIDを使用する大多数のWebサイトの標準的な方法です。

45
Ghedipunk

塩は秘密ではないはずです。その目的はすべてのパスワードで異なるため、ハッシュされたデータベースをRainbowテーブルで攻撃することはできません。あなたが言及する他のパラメータも秘密にされるべきではありません。そのため、このすべての情報を同じデータベースに格納できます。これが、ほとんどのアプリケーションが行う方法です。ハッシュを含むデータベーステーブルには、通常、ソルトとハッシュアルゴリズムに関するその他すべての情報も含まれています。

ハッシュに適切な方法を使用する場合(適切なライブラリを使用し、自分でハッシュアルゴリズムを実装しないでください!)、ブルートフォースしないとパスワードを回復することはできません。だからといってそれが不可能になるわけではありません!弱いパスワードは弱いパスワードのままになるため、12345adminはもちろん簡単に推測できます。

HTTPSはどこでも、いつでも、誰にとっても重要です。攻撃者は外国にいるだけではありません。攻撃者は、同僚、元同僚、訪問者、侵入者、さらには感染したルーターやその他のデバイスです。そのため、できる限りHTTPを削除してください。うまくいけば、いつかHTTPが絶滅するでしょう。

Cookieはセッション管理には問題ありませんが、注意が必要な詳細がいくつかあります。たとえば、HTTPのみのCookieを使用し、Cookieに含まれるセッションIDが本当にランダムであり、推測できないことを確認し、有効期限を設定する必要があるかどうかを決定します(非アクティブな時間が経過するとユーザーはログアウトする必要がありますか?)、等.

9
reed

こちらはソフトウェアエンジニアです。その観点からお答えします。

ローカルネットワークには、シンプルなWebサーバーを実行する多くのデバイスがあります

SSO(シングルサインオン)を使用できるかどうかを実際に確認する必要があります。

詳細を説明する前に、SSOは基本的に保存しないアプリのパスワードです。あなたは、Active Directoryのようなサードパーティの安全なパーティーに依存します。結局のところ、それは企業環境ですか?涼しい

このパスを使いたい場合は、管理する必要がないまたはreinventのセキュリティという主な利点があります。パスワードの処理は簡単なことではなく、既存のオープンソースフレームワークでintegratingではなく、認証システムのコードを記述しなければならないのは、デザインの匂いです。

認証元としてサードパーティを使用すると、その問題から解放され、ユーザーがあまりにも多くのパスワードを使用することを回避できます。繰り返しになりますが、さまざまなSSOのライブラリが周囲にあります 世界 Githubの場合、最初から書き直す必要はありません。

すべてのデバイスのサーバーにパスワードを保存する場合、各サーバーのパスワードの(ハッシュの)コピーが存在し、ユーザーがパスワードを変更するか、リセットしたときに同期されないと考えてください。 5台のデバイスまたは1000台のデバイスがある場合...体験を教えてください!

最も単純なADベースのSSOは、ユーザーがログイン画面でパスワードを入力しても、そのパスワードがポータルに保存されることはなく、検証のために中央ドメインコントローラーに送信されることを意味します。権限管理については説明しません。

Active Directoryは単なる例です。他のツールがあります。

その他のポイントは

現在、すべてがhttpを使用しています。すべてのアクセスがローカルネットワーク内にある場合、httpsは必要ですか?

ユーザーがパスワードを入力するすべての場所で、httpsは必須です。その理由はいくつかあります。

  • 私が述べたActive Directoryパスワードを人々が使用している場合、それはネットワーク上で公開されていることになります(コンピューターにログインするときにMS Windowsは公開しません)。したがって、エンタープライズグレードのセキュリティで保護されていると見なされるシステムに脆弱性が入ります
  • 通常、人々はパスワードを再利用するため、誰かがパスワードを見つけた場合、別の場所で再利用しようとする可能性があります

小規模なオフィスであっても、LANでWiresharkを実行してパスワード(おそらくはマネージャーのパスワード)を盗もうとする悪質なプレイヤーがいる可能性があります。何をすべきか?依存する...給与計算にアクセスする?????

Cookieを使用すると、ユーザーが正常にログインしたことを確認できますか?

Cookieは、ユーザーが認証された後の「記憶」機能に使用されます。したがって、パスワードを再度入力する必要はありません。この回答の範囲については、「はい」と言います。これは良い方法です。しかし、あなたは[〜#〜] must [〜#〜] httpsを使用し、XSRF攻撃からアプリケーションを保護します。ここではそれらについては説明しません。 CookieはGoogleとFacebookで正しい方法で使用されます。彼らがクッキーを使うなら、なぜあなたはそうしてはいけないのですか?

免責事項:私はマイクロソフトからお金をもらっていません。頭に浮かぶ最も単純な例を書いているだけです

このログイン画面をどこに配置するつもりかはわかりませんが、サーバーの一部を書き換えてログインページを追加することを想定しています。 Pythonで言及されている「サーバー」とは何なのか、私にはよくわかりません。

とにかく、パスワードを保存する方法を再発明しないでください。そのための方法はいくつかありますが、Pythonについて言及しているので、出発点としては その件に関するDjangoのドキュメント がよいでしょう。

これにより、セッションを維持する方法も処理されます(たとえば、Cookieを介して)

パスワードの保存に関する一般的な概要については、これを参照してください 2013年の回答 Thomas Pornin著。 Argon2 をハッシュアルゴリズムとして使用することを検討してください。

最後に、あなたは読みたいかもしれません [〜#〜] owasp [〜#〜] その件に関する位置付け、それはそれについて言及しています(私の強調)

暗号化のほとんどの領域と同様に、考慮する必要のあるさまざまな要素がありますが、幸いなことに、現代の言語とフレームワークの大部分は、パスワードを格納するのに役立つ組み込みの機能を提供します。複雑さの大部分

5
WoJ