web-dev-qa-db-ja.com

CSRFトークン生成

これは、CSRFトークンの生成に関する質問です。

通常、ユーザーのセッションに関連付けられた一意のデータに基づいてトークンを生成し、秘密キーでハッシュおよびソルトしたいと思います。

私の質問は、使用する一意のユーザーデータがない場合のトークンの生成に関するものです。使用可能なセッションはありません。Cookieはオプションではありません。IPアドレスとその性質のものは信頼できません。

ハッシュの文字列をリクエストの一部として含めることができない理由はありますか?トークンを生成して埋め込むための擬似コードの例:

var $stringToHash = random()
var $csrfToken = hash($stringToHash + $mySecretKey)
<a href="http://foo.com?csrfToken={$csrfToken}&key={$stringToHash}">click me</a>

CSRFトークンのサーバー側検証の例

var $stringToHash = request.get('key')
var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken')

ハッシュで使用される文字列は、リクエストごとに異なります。各リクエストに含まれている限り、CSRFトークンの検証は続行できます。それは各リクエストで新しく、ページに埋め込まれているだけなので、トークンへの外部アクセスは利用できません。トークンのセキュリティは、私だけが知っている$ mySecretKeyに分類されます。

これは単純なアプローチですか?これが機能しない理由がありませんか?

ありがとう

44
Jim Beam

リクエストの一部としてハッシュする文字列を含めることができない理由はありますか?

CSRFトークンには2つの部分があります。フォームに埋め込まれたトークン、および対応する他のトークンは、Cookie内にあるか、セッションなどに保存されます。他の場所でこのように使用すると、ページが自己完結しなくなります。

リクエストにハッシュする文字列を含めると、リクエストは自己完結型になります。したがって、トークンの両方の部分があるため、攻撃者はフォームをコピーするだけで済み、保護されません。

フォームURLに入れても、それは自己完結型であり、攻撃者はフォームと送信URLをコピーするだけです。

28
blowdart
7
michalzuber

通常、POST=リクエストで適用される)(意図しない)データ変更を防ぐためのCSRFトークン。

したがって、データを変更するリクエストごとにCSRFトークンを含める必要があります(GETまたはPOSTリクエスト)。

私の質問は、使用する一意のユーザーデータがない場合のトークンの生成に関するものです。使用可能なセッションはありません。Cookieはオプションではありません。IPアドレスとその性質のものは信頼できません。

次に、訪問者ごとに一意のユーザーIDを作成します。そのIDをCookieまたはURLに含めます(Cookieが無効な場合)。

編集:

次のイベントを検討してください。

Facebookアカウントにログインしてから、任意のWebサイトにアクセスしました。

そのウェブサイトには、送信するフォームがあります。これは、POSTリクエストをFacebookアカウントに送信するようにブラウザに指示します。

そのPOSTリクエストはパスワードを変更したりコメントを追加したりすることがあります。これは、facebookアプリケーションがあなたを登録済みおよびログイン済みユーザーとして認識しているためです。

2
Dor

URL /フォームとCookieに同じ「トークン」が必要なだけです。つまり、ページでトークンCookieをJavaScriptで任意の値(できればランダムな値)に設定し、サーバーに送信されるすべてのリクエストで同じ値を(URI?paramまたはform-フィールド)。サーバーでCookieを生成する必要はありません。

これは、ブラウザがドメインのページで他のドメインのCookieの編集/読み取りを許可しないことを信頼している限り安全であり、今日では非常に安全であると想定されています。

サーバーにトークンを生成させることで、このトークンはCSRFの試行によって取得されることなく安全にブラウザに送信できると想定されます(リスクを負う理由)。サーバーで生成されたトークンにもっとロジックを入れることもできますが、CSRFを防ぐために必要はありません。

(ここで間違っている場合はお知らせください)

1
MyGGaN

CSRFトークンには複数の実装があります。重要なことは、このcsrfトークンがクライアント側で生成されるか、サーバー側で生成されるかです。これらの2つのシナリオとトークンのエントロピーのために実装が大幅に変更されるためです。

サーバー側ではSecureRandomが推奨されますが、ユーザーを特定する前にCSRFトークンを生成したい場合、 window.cryptounguessableを生成できるこの機能を提供しますCSRFトークンに使用するのに十分な文字列。

1
user1744119

CSRF攻撃は攻撃者が被害者のブラウザを利用してログインステータスを偽造するため、あなたのアプローチが機能すると言いたいのですが、なぜそうできるのですか?ほとんどのサーバー側ではセッションチェックがCookieのSessionIDに基づいているため、Cookieはサーバーに送信されるHTTP要求に自動的に添付されます。

したがって、CSRFを守るには2つの重要な要素があります

  1. チャレンジトークンを生成し、URL paramまたはPOST形式は問題ありません。
  2. たとえば、SSLを使用して、SessionIDに対して行ったことと同じようにトークンを安全に保ちます。

CSRF防止チートシート を読むことをお勧めします

1
Frank Zhang

HMACに基づいてハッシュを作成するのが最善の方法だと思います。つまり、ハッシュを何らかのパスワードで暗号化するには、username + user_id + timestampというシーケンスを使用します。ハッシュはリクエストごとに異なる必要があり、タイムスタンプは、攻撃時にハッシュを簡単にリプレイしたくない場合に使用する必要があります。

0
dynax60