web-dev-qa-db-ja.com

取り消すことができる1回限りのURLの生成

次の機能を備えた1回限りのURLを生成する必要があります。

  1. URLクエリパラメータには機密情報が含まれている可能性があるため、(https暗号化に加えて)暗号化する必要があります。
  2. 一度使用すると、そのURLを再び使用することはできません。
  3. URLは、一定の時間が経過すると自動的に期限切れになります。
  4. 管理者は、有効なURLを取り消すことができます。後でユーザーがこのURLを使用しようとすると、適切なエラーメッセージが表示されます。

これを行うには、2つの高レベルのアプローチを考えることができます。

  1. URLのクエリパラメータとして乱数を生成します。乱数と対応するパラメーター(つまり、実際のクエリパラメーター、有効期限、失効ステータス、使用済みステータス)をデータベースに保存します。ユーザーがURLを使用する場合は、実際のクエリパラメータを指定する前に、必要なすべての前提条件を確認し、使用済みとしてマークしてください。
  2. 実際のクエリパラメータと有効期限タイムスタンプをURLのクエリパラメータとして埋め込みます。 AES256などのアルゴリズムでURLを暗号化します。ただし、失効機能を提供するために、データベースにURLを保存する必要があります。

上記に基づいて、すべてのロジックが単一の場所にあり、より安全に見えるため、私はオプション1に傾いています。この種の問題に対処するための業界のベストプラクティスはありますか?

重要な場合、これはIISでホストされるRESTベースのWebサービスになります。

27
Rao Nagaraj

あなたはあなたが何をしているかかなり良い考えを持っているように見えます。

1回限りのリンクパターンは、メールの確認などによく使用されます。通常、有効期限はデータベースに保存するか、署名する文字列に有効期限を含むURLで署名付き文字列を使用します。これらは、ユーザー入力を信頼しないようにするための予防策にすぎません。

徹底したい場合は、実際のランダムIDまたはトークンURLを送信し、データベースにハッシュを保存して、データ侵害があった場合に誰かがトークンを使用するのを防ぐことができます。

提案されたAES暗号化パラメーターのコンテキストについてはかなり曖昧です。通常、URLの代わりに、URLルーティングに必要のない機密情報をメッセージ本文に含めます。これにより、Webサーバーやプロキシログに表示されなくなります。 AESで暗号化されたデータは、プレーンテキストコンテンツのサイズに応じて、URLの長さの制限を大幅に超える可能性があります。

編集:完全を期すために、 Azure Storage SAS Tokens は暗号化の良い例ですデータベースレコードを必要とせず、取り消し可能なメソッド。取り消しは、サービスのAPIキーを変更することで行われます...同じキーによって発行されたallトークンを取り消します。

使用しているシステムに関する情報が少ないので、暗号化された高度な手段が必要なソリューションよりも、データベースの検索を単純化することをお勧めします。

また、暗号化方式がワンタイムリンクとして機能するためには、サービスが認識し、URLに含まれているいくつかのパラメーターを、リンクを使用するときに変更する必要があります。このパラメーターはデータベース参照である必要はありませんが、永続的な変更が必要です。たとえば、リンクが1回限りのアップロードURLの場合、アップロードディレクトリにファイルが存在すると、URLが無効になる可能性があります。

最後に、データベースに保存された値は、有効性をチェックするソースが1つしかないという点で単純です。データベースを使用しないソリューションでは、シークレット(つまり、暗号化キー)をチェックする必要があります。また、最初の使用後にリンクを無効にする要因も確認する必要があります。

26
nbering

URLパラメータに対称暗号を使用すると、1つの利点が得られます。データベースの検索を行う必要がなくなります。欠点は、保護および維持する必要がある秘密(暗号化キー)を導入することです。失効ステータスを確認するためにとにかくデータベースルックアップを行う必要があるので、上向きになることはありません。だから私はアプローチ#1に行きます。

十分な長さのIDを使用し、CSPRNGで生成してください。そして nbering が言うように、違反した場合にあなたを保護するためにそれらを(塩なしで)ハッシュしてください。

10
Anders

Googleのような巨大なソフトウェアは、署名付きURLの方法を使用しています

前提は単純です。クエリの暗号化されていない側に一致する暗号化された文字列を使用してリクエストを送信します。次に、サーバー上でそれを復号化するだけです。

例えば

example.com?file=file.ext&time={unixtimecode}&{encryptedstringthatmatchesfileandtimestamp}

暗号化キーの使用は、キーにアクセスできるサーバー/誰かが、ユーザーが一定期間フォローできるリクエストを作成し、リクエストが改ざんされていないことを確認することです。文字列を取り消すのは、一時的な暗号化キーを削除するのと同じくらい簡単です。つまり、キャッシュされていても、サーバーは要求を復号化できません。

4
user9569328