5

私は彼に送信されるすべてのリクエストに対して次のことを保証するRESTWebサービスを考えています:

  • リクエストは、それを主張するユーザーによって生成されました;
  • リクエストは他の誰かによって変更されていません(uri / method / content / date);
  • GETリクエストの場合、署名を確認して有効期限を設定するのに十分な情報を含むURIを生成できる必要があります。このようにして、ユーザーは、生成されたURIを使用して、リソース上の限られた期間、一時的なREAD権限を共同編集者に委任できます。

クライアントは、パスワードに基づいてIDとコンテンツ署名で認証されます。

セッションはまったく存在しないはずなので、サーバーの状態です。サーバーとクライアントは秘密鍵(パスワード)を共有します

それについて考え、本当に素晴らしい人々と話をした後、私のユースケースのように単純なことを行うためのRESTサービスは存在しないようです。(HTTPダイジェストとOAuthはサーバーの状態でこれを行うことができ、非常におしゃべりです)

それで私は1つを想像しました、そして私はそれがどのように設計されるべきかについてあなたの偉大なコメントを求めています(私はそれをOpenSourceにリリースし、それが他の人を助けることができることを願っています)。

このサービスは、カスタムの「Content-signature」ヘッダーを使用して資格情報を保存します。認証されたリクエストには、次のヘッダーが含まれている必要があります。

Content-signature: <METHOD>-<USERID>-<SIGNATURE>

<METHOD> is the sign method used, in our case SRAS.
<USERID> stands for the user ID mentioned earlier.
<SIGNATURE> = SHA2(SHA2(<PASSWORD>):SHA2(<REQUEST_HASH>));
<REQUEST_HASH> = <HTTP_METHOD>\n
                 <HTTP_URI>\n
                 <REQUEST_DATE>\n
                 <BODY_CONTENT>;

リクエストは、作成されてから10分後に無効になります。

たとえば、一般的なHTTPリクエストは次のようになります。

POST /ressource HTTP/1.1
Host: www.elphia.fr
Date: Sun, 06 Nov 1994 08:49:37 GMT
Content-signature: SRAS-62ABCD651FD52614BC42FD-760FA9826BC654BC42FD

{ test: "yes" }

サーバーは答えます:

401 Unauthorized

また

200 OK

変数は次のようになります:

<USERID> = 62ABCD651FD52614BC42FD
<REQUEST_HASH> = POST\n
                 /ressource\n
                 Sun, 06 Nov 1994 08:49:37 GMT\n
                 { test: "yes" }\n

URIパラメータ

いくつかのパラメーターをURIに追加できます(それらはヘッダー情報をオーバーロードします):

  • _sras.content-signature = <METHOD>-<USERID>-<SIGNATURE>:HTTPヘッダーではなく、URIにクレデンシャルを配置します。これにより、ユーザーは署名されたリクエストを共有できます。
  • _sras.date = Sun、06 Nov 1994 08:49:37 GMT(リクエスト日*):リクエストが作成された日付。
  • _sras.expires = Sun、06 Nov 1994 08:49:37 GMT(有効期限*):サーバーにリクエストが指定された日付より前に期限切れにならないように指示します

*日付形式:http ://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18

コメントしてくれてありがとう。

4

2 に答える 2

5

シグニチャプロトコルを設計する際に考慮する必要のある問題がいくつかあります。これらの問題の一部は、特定のサービスに当てはまらない場合があります。

1-非標準ヘッダーに「X-Namespace-」プレフィックスを追加するのが通例です。この場合、ヘッダーに「X-SRAS-Content-Signature」のような名前を付けることができます。

2- Dateヘッダーは、nonce値に対して十分な解像度を提供しない可能性があるため、少なくとも1ミリ秒の解像度を持つタイムスタンプをお勧めします。

3-少なくとも最後のナンスを保存しない場合でも、10分ウィンドウでメッセージを再生できます。これはPOSTリクエストではおそらく受け入れられません(REST Webサービスで同じ値の複数のインスタンスを作成する可能性があります)。これは、GETPUTまたはDELETE動詞では問題になりません。

ただし、PUTで​​は、提案された10分のウィンドウ内に同じオブジェクトを何度も更新することを強制することにより、これをサービス拒否攻撃に使用できます。GETまたはDELETEでも、同様の問題が発生します。

したがって、少なくとも各ユーザーIDに関連付けられた最後に使用されたナンスを保存し、この状態をすべての認証サーバー間でリアルタイムで共有する必要があります。

4-この方法では、クライアントとサーバーが10分未満のスキューでクロック同期されている必要もあります。これは、デバッグが難しい場合や、クロックを制御していないAJAXクライアントがある場合は強制することが不可能な場合があります。これには、すべてのタイムスタンプをUTCで設定する必要もあります。

別の方法は、10分のウィンドウ要件を削除することですが、タイムスタンプが単調に増加することを確認します。これも、最後のナンスを格納する必要があります。クライアントの時計が最後に使用されたナンスより前の日付に更新された場合、これは依然として問題です。クライアントのクロックが最後のナンスを通過するか、サーバーのナンス状態がリセットされるまで、アクセスは拒否されます。

単調に増加するカウンターは、クライアントが最後に使用されたナンスをサーバーに要求できない限り、状態を格納できないクライアントのオプションではありません。これは、各セッションの開始時に1回実行され、その後、要求ごとにカウンターが増分されます。

5-ネットワークエラーによる再送信にも注意を払う必要があります。TCP接続が切断される前に、クライアントがTCPAckを受信して​​いない最後のメッセージをサーバーが受信していないと想定することはできません。したがって、ナンスは、TCPレベルを超える各再送信と、新しいナンスで再計算された署名との間でインクリメントする必要があります。ただし、サーバーでの二重実行を防ぐためにメッセージ番号を追加する必要があります。二重POSTを実行すると、2つのオブジェクトが作成されます。

6-ユーザーIDにも署名する必要があります。そうしないと、攻撃者は、再生されたメッセージのメッセージにまだ到達していないすべてのユーザーに対して同じメッセージを再生できる可能性があります。

7-あなたの方法は、サーバーが本物であり、DNSハイジャックされていないことをクライアントに保証しません。サーバー認証は通常、安全な通信にとって重要であると考えられています。このサービスは、リクエストと同じナンスを使用して、サーバーからの応答に署名することで提供できます。

于 2010-12-26T20:27:12.747 に答える
1

これは、OAuth、特にクライアントとサーバーがシークレットを共有する「2本足のOAuth」で実現できることに注意してください。https://www.rfc-editor.org/rfc/rfc5849#page-14を参照してください。あなたの場合、oauth_tokenパラメータを省略し、おそらくHMAC-SHA1署名方式を使用したいとします。これについて特におしゃべりなことは何もありません。この方法で処理を行うために、OAuthトークンの取得フローを実行する必要はありません。これには、いくつかの既存のオープンソースOAuthライブラリのいずれかを使用できるという利点があります。

サーバー側の状態に関しては、どのシークレットがどのクライアントに適用されるか、およびどのナンスが最近使用されたかを追跡する必要があります(リプレイ攻撃を防ぐため)。HTTPSを介して処理を実行する場合は、ナンスチェック/ライフタイムをスキップできますが、それを実行する場合は、HTTPS +基本認証により、新しいソフトウェアを作成しなくても、説明したすべてが提供されます。

于 2010-12-26T13:16:48.080 に答える