web-dev-qa-db-ja.com

クライアント/サーバー関係のセッションIDアルゴリズムの選択

クライアントとサーバーの関係にあるアプリケーションを開発していますが、セッション識別子を決定するアルゴリズムを決定するのに苦労しています。私の目標は、詐欺師が他のユーザーの個人データを取得するのを制限することです。


私は2つのオプションを検討しています:

オプション1:ランダムな32文字の16進数文字列を生成し、データベースに保存し、クライアントログインが成功したときにサーバーからクライアントに渡します。次に、クライアントはこの識別子を保存し、それをサーバーへの今後のリクエストで使用します。これにより、保存された識別子との照合が行われます。

オプション2:セッションの開始時間とクライアントのログインユーザー名および/またはハッシュされたパスワードの組み合わせからハッシュを作成し、それをサーバーへの今後のすべての要求に使用します。セッションハッシュは、最初のリクエスト時にデータベースに格納され、クライアントからの今後のリクエストについてクロスチェックされます。

その他の情報:複数のクライアントを同じIPから同時に接続でき、2つのクライアントが同じセッション識別子を持つことはできません。


質問:それぞれの懸念(下記)に関して、これらのオプションのどちらがより良いアプローチですか?

最初のオプションに対する私の懸念は、識別子が完全にランダムであるため、偶然に複製される可能性があることです(ただし、の1である3.4 * 1038チャンス)、1人のユーザー(同時にクライアントも使用する必要がある)のプライベートデータを「盗む」ために使用されます。

2番目のオプションに対する私の懸念は、セキュリティ上の欠陥があることです。つまり、ユーザーのハッシュ化されたパスワードが何らかの方法で傍受されると、セッションハッシュ全体が盗まれ、ユーザーのプライベートデータが盗まれる可能性があります。

すべての入力をありがとう。

23
FThompson

セッション識別子の基本的な概念は、サーバーの制御下にある(つまり、コードの制御下にある)動的な関係であるsessionの有効期間が短い秘密の名前であるということです。セッションの開始と停止を決めるのはあなた次第です。成功するセッション識別子生成アルゴリズムの2つのセキュリティ特性は次のとおりです。

  1. 圧倒的な確率で、2つの異なるセッションが同じ識別子を持つことはありません。
  2. ランダムなものを試行するときに、無視できない確率でセッション識別子を「ヒット」することは、計算上実行可能であってはなりません。

これらの2つのプロパティは、ジェネレーターが 暗号的に強力なPRNG (UNIXでは_/dev/urandom_)である場合、少なくとも16バイト(16進表記の32文字)のランダムセッションIDで実現されます。のようなシステム、Windows/Win32ではCryptGenRandom() 、. NETではRNGCryptoServiceProvider)。データベースサーバーサイドにもセッションIDを保存するため、could重複をチェックします。実際、データベースがおそらくそれを行います(このIDをインデックスキーにする必要があります)が、確率が非常に低いため、それは時間の浪費です。家を出るときはいつも、落雷に遭わないという考えに賭けていることを考慮してください。雷に殺される確率は約3 * 10です。-10 1日あたり( 本当に )。正確には、それは生命を脅かすリスク、あなた自身の人生です。それでも、あなたはそれについて考えずに、そのリスクを却下します。では、何百万倍も確率が低く、発生したとしてもだれも殺さないセッションIDの衝突を心配するのは、どういう意味でしょうか。

Thingで追加のハッシュ関数をスローしても意味がありません。適切に適用されたランダム性は、すでに必要なすべての一意性を提供します。複雑さが増しても、弱点が増えるだけです。

暗号化機能は、セッションが必要なだけでなく、サーバーベースのストレージコストも回避したいシナリオに関連しています。たとえば、サーバーにデータベースがないとします。この種類の状態オフロードには [〜#〜] mac [〜#〜] とおそらく暗号化が必要です(詳細については この答え を参照してください)。

28
Thomas Pornin

セッションIDは、暗号強度がランダムで一意である必要があります。攻撃者が正当なセッションIDを推測できる場合、そのユーザーになりすます可能性があります。

適切なCSPRNGを使用している限り、オプション1が最善の策であり、標準ライブラリのRand()のようなものではありません。オプション2のようなものを使用することは、ユーザー名と時間が簡単に推測またはブルートフォースされるため、安全ではありません。

PHPのセッションIDジェネレーターコード のしくみを確認すると、クライアントのIPアドレス、現在の時刻(秒とマイクロ秒)、およびいくつかの値を組み合わせるためにハッシュ関数が使用されていることがわかります。 PHPの線形合同生成器(LGC)RNGをベースラインとして使用。 OS固有のランダムソースが利用可能な場合、その関数からのIDにさらにエントロピーが混合されます。これにより、強力なエントロピーソースが利用できない場合は妥当なセキュリティマージンが得られますが、利用できる場合は強力なセキュリティが提供されます。

6
Polynomial

セッションIDに署名する必要があります。そうすれば、セッションIDを推測しようとする人々について心配する必要はありません。

また、衝突がないかどうかを確認して、その識別子をまだ渡していないことを確認してください。