web-dev-qa-db-ja.com

REST Webサービス認証トークンの実装

クラウドサービスとしてAzureでホストされるC#を使用してREST Webサービスを実装しています。これはRESTサービスであるため、ステートレスであり、したがって、Cookieやセッション状態はありません。

WebサービスにはHTTPS(StartSSL.comによって提供される証明書)経由でのみアクセスできます。

ユーザーがサービスに正常にログインすると、セキュリティトークンを取得します。このトークンは、将来の通信で認証を提供します。

トークンには、クライアントのタイムスタンプ、ユーザーID、IPアドレスが含まれます。

すべての通信はHTTPSを介してのみ行われるため、トークンが傍受されてリプレイアタックで使用されることは心配していません。とにかくトークンには有効期限があります。

これは公開サービスであるため、誰かがサービスに登録し、ログインして、受け取ったトークンを変更して他のユーザーのアカウントにアクセスできるのではないかと心配しています。

トークンのコンテンツを保護し、改ざんされていないことを確認するのに最適な方法を考えています。

トークンを保護するために、次のことを計画しています。

クライアントはサービスに正常にログインし、サービスは次のことを行います。

  1. ランダムな値を生成し、それをSHA256で1000回ハッシュします。
  2. 秘密鍵+ハッシュ化されたランダム値からワンタイムセッションキーを生成します。
  3. セッションキーをSHA256で1000回ハッシュし、それを使用してトークンを暗号化する
  4. 秘密鍵を使用して、RSAを使用する暗号化トークンに署名します。
  5. 暗号化されたトークン+署名+ハッシュされたランダム値を、暗号化されていないJSONパッケージでクライアントに送信します。

クライアントがサービスを呼び出すと、クライアントは暗号化されたトークンと署名を暗号化されていないJSONパッケージでサービスに送信します。サービスは

  1. 秘密鍵+ハッシュされたランダム値からセッション鍵を再作成します
  2. 秘密鍵を使用して署名を検証する
  3. ハッシュされたセッションキーを使用してトークンを復号化する
  4. トークンの有効期限が切れていないことを確認してください
  5. 要求された操作を続行してください...

暗号化について何も知らないので、いくつか質問があります。

  1. これで十分ですか、それともやりすぎですか?
  2. 私は改ざんを検出するためにHMACをトークンに含める必要があることを読みました。秘密鍵で署名しているので、HMACは必要ですか?
  3. RSAではなくRijndaelを使用する必要がありますか?
  4. Rijndaelが優先される場合、生成されたIVは復号化に必要ですか?つまり、それを破棄できますか、それとも暗号化されたトークンを送信する必要がありますか?例えば暗号化トークン+ HMAC + IV +ハッシュされたランダム値。

すべての通信はHTTPS経由で行われるため、暗号化されていないJSONパッケージは、クライアントに到達するまで実際には暗号化されません。

また、PHPでサービスを再実装したいので、PHPでも実行できるようにする必要があります。

ご協力いただきありがとうございます

21

あなたは本当にトークンを考えすぎています。正直なところ、最高のトークンセキュリティはランダム性、より正確にはnpredictabilityに依存しています。最高のトークンは完全にランダムです。懸念事項は、ユーザーが自分のトークンを変更し、それを使用して他のユーザーのアカウントにアクセスすることです。これは、「セッション盗用」と呼ばれる一般的な攻撃です。トークンがランダムに生成され、サーバー側で期限切れになる場合、この攻撃はほぼ不可能です。 IPやタイムスタンプなどのユーザー情報を使用すると、予測可能性が向上するため、不適切です。私は大学で攻撃を行い、サーバーのタイムスタンプに基づいたマイクロ秒単位のアクティブなトークンを推測することに成功しました。アプリケーションの作成者は、マイクロ秒は予測不能になるほど速く変化すると考えていましたが、そうではありませんでした。

ユーザーがプロキシサーバーの背後にいる場合、プロキシはSSLリクエストをプレーンテキストで表示することがあります(セキュリティ上の理由から、多くのプロキシは詳細なパケット検査を実行します)。このため、セッションを期限切れにすることをお勧めします。そうしなかった場合、ユーザーはこのような攻撃、および可能性のあるXSSとCSRFに対して脆弱になります。

RSAまたはRijndaelは、妥当な長さの鍵を提供すれば十分です。また、トークンにHMACを使用して、署名している場合でも改ざんを防止する必要があります。秘密鍵で署名しているので、理論的には冗長になります。ただし、HMACは十分にテストされており、署名メカニズムの実装に欠陥がある可能性があります。そのため、HMACを使用することをお勧めします。 「独自のロール」セキュリティ実装に欠陥があり、セキュリティを侵害することに驚かれるでしょう。

あなたはセキュリティにかなり精通しているように見えます。今後ともよろしくお願いいたします。この世界では、セキュリティを意識した開発者がもっと必要です。

編集:

サーバーのみが持つ強力な対称秘密鍵(AES、Blowfishな​​ど)で暗号化されている限り、トークンにタイムスタンプ/ユーザーIDを含めても安全であると見なされます。トークンには、HMACなどの改ざん防止ハッシュが含まれていますユーザーID /タイムスタンプとともに秘密鍵で暗号化されています。ハッシュは整合性を保証し、暗号化は機密性を保証します。

暗号化にHMAC(またはその他のハッシュ)を含めない場合、ユーザーが暗号化されたトークンを改ざんし、有効なものに復号化させることが可能です。ユーザーIDとタイムスタンプが暗号化され、ハッシュなしのトークンとして使用されているサーバーに対して攻撃を行いました。文字列のランダムな1文字を変更することで、ユーザーIDを58762から58531のようなものに変更できました。「新しい」ユーザーIDを選択することはできませんでしたが、他のユーザーのアカウントにアクセスできました(これは学界にありました) 、コースの一部として)。

これに代わる方法として、完全にランダムなトークン値を使用し、サーバー側で保存されているユーザーID /タイムスタンプ(サーバー側に留まるため、クライアントの制御外にある)にマッピングします。これは少しメモリと処理能力を必要としますが、より安全です。これは、ケースバイケースで行う必要がある決定です。

IVや他のキーからのキーの再利用/派生については、キーが短期間のみ有効であるという条件で、これは通常問題ありません。数学的には、誰かがそれらを壊す可能性は低いです。しかし、それは可能です。偏執的なルートに行きたい場合(私は通常そうします)、すべての新しいキーをランダムに生成します。

26
Freedom_Ben