Rails Authenticityトークンについて


983

RailsのAuthenticityトークンに関する問題が何度か発生しています。

しかし、私は本当にこの問題を解決して続行したくありません。Authenticityトークンについて本当に理解したいと思います。さて、私の質問は、このテーマに関する完全な情報源はありますか、またはここで詳細に説明するためにあなたの時間を費やしますか?


7
「GoogleがJSON応答の前にwhile(1)を付加する理由」も参照してください。stackoverflow.com/questions/2669690/...
クロエ

回答:


1463

何が起こるのですか

ユーザーがフォームを表示してリソースを作成、更新、または破棄すると、Railsアプリはランダムを作成し、authenticity_tokenこのトークンをセッションに保存して、フォームの非表示フィールドに配置します。ユーザーがフォームを送信すると、Railsはを検索し、authenticity_tokenそれをセッションに保存されているものと比較し、一致する場合、リクエストの続行を許可します。

なぜそれが起こるのか

認証トークンはセッションに格納されるため、クライアントはその値を知ることができません。これにより、そのアプリケーション自体内でフォームを表示せずに、Railsアプリケーションにフォームを送信することが防止されます。サービスAを使用していて、サービスにログインしていて、すべてが正常であるとします。ここで、サービスBを使用し、気に入った写真を見て、その写真を押して、より大きいサイズの画像を表示したとします。さて、サービスBに悪質なコードがあった場合、サービスA(ログイン中)にリクエストを送信し、にリクエストを送信して、アカウントの削除を要求する可能性がありますhttp://serviceA.com/close_account。これは、CSRF(Cross Site Request Forgery)として知られているものです。

サービスAが認証トークンを使用している場合、サービスBからの要求には正しい認証トークンが含まれず、続行を許可されないため、この攻撃ベクトルは適用されなくなります。

APIドキュメントでは、メタタグの詳細について説明しています

CSRF保護はprotect_from_forgery、トークンをチェックし、それが予期されたものと一致しない場合にセッションをリセットするメソッドでオンになります。このメソッドの呼び出しは、デフォルトで新しいRailsアプリケーションに対して生成されます。トークンパラメータにはauthenticity_tokenデフォルトで名前が付けられます。このトークンの名前と値はcsrf_meta_tags、HTMLヘッドに含めることでフォームをレンダリングするすべてのレイアウトに追加する必要があります。

ノート

Railsはべき等のメソッド(POST、PUT / PATCH、DELETE)のみを検証することに注意してください。GETリクエストは、認証トークンについてチェックされません。どうして?HTTP仕様では、GETリクエストはべき等であり、サーバーでリソースを作成、変更、または破棄してはなら、リクエストはべき等である必要があるためです(同じコマンドを複数回実行すると、毎回同じ結果が得られるはずです)。

また、実際の実装は、最初に定義したように少し複雑であり、セキュリティが向上しています。Railsはすべてのフォームで同じ保存済みトークンを発行するわけではありません。また、毎回異なるトークンを生成して保存することもありません。セッションで暗号化ハッシュを生成して保存し、ページがレンダリングされるたびに、保存されたものと照合できる新しい暗号化トークンを発行します。request_forgery_protection.rbを参照してください。

レッスン

authenticity_tokenべき等ではないメソッド(POST、PUT / PATCH、DELETE)を保護するために使用します。また、サーバー上のリソースを変更する可能性のあるGETリクエストを許可しないようにしてください。


編集:べき等であるGETリクエストに関する@erturneによるコメントを確認してください。彼は私がここで行ったよりも良い方法でそれを説明しています。


25
@Faisal、その場合、攻撃者がサービスAのフォームの「非表示」要素を単に読み取り/キャプチャし、ユーザーが生成した一意のトークンを取得することができます-ユーザーが開始したセッションへのアクセス権を持っている場合サービスAは?
マルカミリオン

11
@marcamillion:誰かがサービスAでセッションをハイジャックした場合、認証トークンはあなたを保護しません。ハイジャッカーはリクエストを送信でき、続行を許可されます。
ファイサル

12
@zabba:フォームが適切なトークンなしで送信された場合、RailsはActionController :: InvalidAuthenticityToken例外を発生させます。例外からrescue_fromを実行して、必要な処理を行うことができます。
ファイサル

5
「また、サーバー上のリソースを変更する可能性のあるGETリクエストを行わないようにしてください。」-これには、POSTのみを受信することを目的としたコントローラーアクションへのGETリクエストを潜在的に許可する可能性があるルートでmatch()を使用しないことが含まれます
Steven Soroka

102
「...そしてリクエストはべき等である必要があります(同じコマンドを複数回実行すると、毎回同じ結果が得られるはずです)。」ここでは微妙な説明です。安全とは、副作用がないことを意味します。べき等は、サービスが呼び出された回数に関係なく同じ副作用を意味します。副作用がないため、すべての安全なサービスは本質的にべき等です。現在のリソースでGETを複数回呼び出すと、毎回異なる結果が返されますが、安全です(したがって、べき等です)。
erturne 2012

137

認証トークンは、フォームがWebサイトから送信されていることがわかるように設計されています。それはあなたのマシンだけが知ることができるユニークな識別子でそれが走っているマシンから生成され、クロスサイトリクエストフォージェリ攻撃を防ぐのを助けます。

AJAXスクリプトアクセスを拒否するレールに単に問題がある場合は、

<%= form_authenticity_token %>

フォームの作成時に正しいトークンを生成します。

詳細については、ドキュメントをご覧ください。


88

CSRFとは

Authenticity Tokenは、Cross-Site Request Forgery(CSRF)への対策です。CSRFとは何ですか?

これは、攻撃者がセッショントークンを知らなくてもセッションを乗っ取る可能性がある方法です。

シナリオ

  • 銀行のサイトにアクセスしてログインします。
  • 次に、攻撃者のサイトにアクセスします(信頼されていない組織のスポンサー広告など)。
  • 攻撃者のページには、銀行の「送金」フォームと同じフィールドを持つフォームが含まれています。
  • 攻撃者はあなたのアカウント情報を知っており、あなたのアカウントから攻撃者のアカウントに送金するための事前入力されたフォームフィールドがあります。
  • 攻撃者のページには、銀行にフォームを送信するJavascriptが含まれています。
  • フォームが送信されると、ブラウザにはセッショントークンを含む銀行サイトのCookieが含まれます。
  • 銀行は攻撃者の口座に送金します。
  • フォームは非表示のiframe内に存在する可能性があるため、攻撃が発生したことは決してわかりません。
  • これは、クロスサイトリクエストフォージェリ(CSRF)と呼ばれます。

CSRFソリューション

  • サーバーはサーバー自体から送信されたフォームをマークできます
  • すべてのフォームには、非表示フィールドとして追加の認証トークンが含まれている必要があります。
  • トークンは予測不可能である必要があります(攻撃者は推測できません)。
  • サーバーは、ページ内のフォームで有効なトークンを提供します。
  • サーバーはフォームの投稿時にトークンをチェックし、適切なトークンなしでフォームを拒否します。
  • トークンの例:サーバーの秘密鍵で暗号化されたセッション識別子。
  • Railsはそのようなトークンを自動的に生成します。すべてのフォームのauthenticity_token入力フィールドを参照してください。

1
ここではあまり正確でなく、あまり抽象的であるこの同じ説明のバージョンは次のとおりです。stackoverflow.com/a/33829607/2810305
ルッツPrechelt

よくわかりませんが、最近のブラウザでは、べき等ではないリクエスト(POST / PUT / DELETE)を別のドメインに送信できますか?私は、ブラウザ自体にそのようなものに対する保護があるはずだと思います
divideByZero

45

防止される最小限の攻撃の例:CSRF

私のウェブサイトでevil.com、次のフォームを送信するように説得します。

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

セッションCookieを使用して銀行にログインしている場合は、Cookieが送信され、知らないうちに転送が行われます。

つまり、CSRFトークンが機能します。

  • フォームを返したGET応答で、Railsは非常に長いランダムな非表示パラメーターを送信します
  • ブラウザがPOSTリクエストを行うと、パラメータが送信され、サーバーは一致する場合にのみそれを受け入れます

したがって、本物のブラウザのフォームは次のようになります。

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

したがって、authenticity_tokenパラメータを送信していないため、攻撃は失敗します。これは、巨大な乱数であるため、それを推測することはできませんでした。

この防止手法は、シンクロナイザトークンパターンと呼ばれます。

同一生成元ポリシー

しかし、攻撃者がJavaScriptで2つの要求を行った場合、1つはトークンを読み取り、もう1つは転送を行うとどうなるでしょうか。

シンクロナイザトークンパターンだけでは、それを防ぐのに十分ではありません。

私が/security/8264/why-is-the-same-origin-policy-so-important/72569#で説明したように、これがSame Origin Policyが役に立ちます。 72569

Railsがトークンを送信する方法

対象:Rails:csrf_meta_tagはどのように機能しますか?

基本的に:

  • HTMLヘルパーform_tagは、GETフォームではない場合にフォームに非表示フィールドを追加するようなものです。

  • AJAXはjquery-ujsによって自動的に処理されます。jquery-ujsは、(デフォルトのテンプレートに存在する)metaによってヘッダーに追加された要素からトークンを読み取り、csrf_meta_tags行われたすべてのリクエストにトークンを追加します。

    uJSはまた、古いキャッシュフラグメントの形式でトークンを更新しようとします。

その他の予防アプローチ


ありがとうございます。しかし、CSRFトークンを単に読み取ることができないように同じ生成元のポリシーに依存することについてのあなたの主張は、最初に欠陥があるようです。したがって、最初に別のオリジンにPOSTできるが、そこから読み取れないと言ったのは奇妙に思われますが、それは正しいと思いますが、ページにアクセスして画像またはスクリプトタグを挿入し、ハンドラーをリンクして応答を解析できますはいそれを得ますか?
bjm88

@ bjm88はスクリプトをどこに挿入しますか?あなたのサイト、または攻撃されたサイト?サイトが攻撃された場合、スクリプトインジェクションを許可することはよく知られたセキュリティ上の欠陥であり、効果的にWebサイトをポーンします。すべてのウェブサイトは、入力衛生を通じてそれと戦わなければなりません。画像の場合、攻撃にどのように使用できるかわかりません。攻撃サイト:読み取りを許可するようにブラウザーを変更して、自分で自由にポーンできます:-)しかし、適切なブラウザーはデフォルトでそれを阻止しますので、試してみてください。
Ciro Santilli冠状病毒审查六四事件法轮功

43

認証トークンは、クロスサイトリクエストフォージェリ攻撃(CSRF)を防ぐために使用されます。認証トークンを理解するには、まずCSRF攻撃を理解する必要があります。

CSRF

あなたがの作者であるとしますbank.com。GETリクエストで別のアカウントに送金するために使用するフォームがサイトにあります。

ここに画像の説明を入力してください

ハッカーは、サーバーにHTTPリクエストを送信してGET /transfer?amount=$1000000&account-to=999999、と言ってもいいでしょう?

ここに画像の説明を入力してください

違う。ハッカーの攻撃は機能しません。サーバーは基本的に考えますか?

えっ?転送を開始しようとしているこの男は誰ですか。それは確かにアカウントの所有者ではありません。

サーバーはどのようにこれを知っていますか?ないのでsession_idリクエスタを認証するCookieです。

ユーザー名とパスワードを使用してサインインすると、サーバーはsession_idブラウザーにCookieを設定します。そうすれば、ユーザー名とパスワードを使用して各リクエストを認証する必要がなくなります。ブラウザがsession_idCookieを送信すると、サーバーは次のことを認識します。

ああ、それはジョン・ドーです。彼は2.5分前に正常にサインインしました。彼はいいです。

ハッカーは次のように考えるかもしれません:

うーん。通常のHTTPリクエストは機能しませんが、もしそのsession_idCookieを手に入れることができれば、私は金色になるでしょう。

ユーザーのブラウザには、bank.comドメインに設定された一連のCookieがあります。ユーザーがbank.comドメインにリクエストを行うたびに、すべてのCookieが送信されます。含んでいるsession_idクッキーます。

だからハッカーがあなたを手に入れることができるなら自分の口座にお金を転送GETリクエストを作るために、彼は成功するだろう。どのように彼はあなたをだましてそうすることができますか?クロスサイトリクエストフォージェリあり。

それは実際にはかなり単純です。ハッカーはあなたに彼のウェブサイトを訪問させるだけかもしれません。彼のウェブサイトでは、彼は次のイメージタグを持つことができます:

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

ユーザーのブラウザーがそのイメージタグに出くわすと、そのURLに対してGETリクエストが行われます。リクエストは彼のブラウザからのものなので、に関連付けられているすべてのCookieが一緒に送信されますbank.com。ユーザーが最近サインインした場合、bank.com... session_idCookieが設定され、サーバーはユーザーが$ 1,000,000をアカウント999999に転送しようとしたものと見なします。

ここに画像の説明を入力してください

まあ、ちょうど危険なサイトを訪問しないでください、あなたは大丈夫です。

それだけでは不十分です。誰かがその画像をFacebookに投稿し、あなたの壁に表示された場合はどうなりますか?XSS攻撃でアクセスしているサイトに挿入された場合はどうなりますか?

そう悪くはない。GETリクエストのみが脆弱です。

違います。POSTリクエストを送信するフォームは動的に生成できます。セキュリティに関するRailsガイドの例を次に示します。

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

真正性トークン

あなたApplicationControllerがこれを持っているとき:

protect_from_forgery with: :exception

この:

<%= form_tag do %>
  Form contents
<% end %>

これにコンパイルされます:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

特に、以下が生成されます。

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

CSRF攻撃から保護するために、Railsがリクエストと共に送信された認証トークンを認識しない場合、リクエストは安全であるとは見なされません。

攻撃者はどのようにしてこのトークンが何であるかを知っているはずですか?フォームが生成されるたびに、異なる値がランダムに生成されます。

ここに画像の説明を入力してください

クロスサイトスクリプティング(XSS)攻撃-その方法です。しかし、それは別の日に別の脆弱性です。


39

「クロスサイトリクエストフォージェリ(CSRFまたはXSRF)攻撃」Authenticity Token防ぐため のis railsメソッド

簡単に言うと、WebアプリへのPUT / POST / DELETE(コンテンツを変更できるメソッド)リクエストが、作成されたCookieにアクセスできるサードパーティ(攻撃者)からではなく、クライアントのブラウザから行われるようにします。クライアント側で。


34

それAuthenticity Tokenはとても重要なので、Rails 3.0 以降では

 <%= token_tag nil %>

作成する

<input name="authenticity_token" type="hidden" value="token_value">

どこでも


これは役に立ちました。私は実際にはXSS悪質な目的ではなく、ログインページで実行しようとしていたが、事前に入力されたユーザー名で新しいセッションを作成しようとしていた。今、私はただ使うことができることを知っていますvalue="token_value"
マイケル-クレイシャーキーはどこですか

27

Authenticity Tokenメカニズムは、同じクライアントから複数の同時要求がある場合に競合状態を引き起こす可能性があることに注意してください。この状況では、サーバーは1つしか存在しないはずの複数の認証トークンを生成でき、フォームで以前のトークンを受け取ったクライアントは、セッションCookieトークンが上書きされているため、次のリクエストで失敗します。この問題についての説明があり、完全に簡単な解決策はありません:http : //www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


11

メソッドauthenticity_token必要な場所

authenticity_token べき等メソッドはデータに影響を与えるため、post、put、deleteなどのべき等メソッドの場合は必須です。

必要な理由

邪悪な行為を防ぐ必要があります。authenticity_tokenはセッションに保存されます。リソースを作成または更新するためにWebページでフォームが作成されると、認証トークンが非表示フィールドに保存され、サーバー上のフォームとともに送信されます。アクションを実行する前に、ユーザーが送信したauthenticity_tokenがauthenticity_tokenセッションに格納されているかどうかがクロスチェックされます。authenticity_token同じ場合、プロセスは続行されます。それ以外の場合、アクションは実行されません。


3
実は逆ではないですか?GETは呼び出しがシステムの状態を変更してはならないため、べき等です。PUTPOSTおよびDELETE動詞は、システムの状態を変更するため、べき等動詞ではありません。IE:べき等でないメソッドの場合、authenticity_tokenが必要です。
ジャン・テオ・

2
@ Jean-Daube、uma:べき等は、2回実行した場合、アクションは1回だけ発生することを意味します。GET、PUTとDELETEがあるべき等:w3.org/Protocols/rfc2616/rfc2616-sec9.htmlここで重要な特性は、冪等ではありませんが、もし「安全なメソッド」と呼ばれたりされていないメソッドの変更やデータではなく、。
Ciro Santilli冠状病毒审查六四事件法轮功

6

authentication_tokenとは何ですか?

これは、ユーザーが別のアプリやサイトからではなく、アプリのページからアクションをリクエストまたは実行していることを確認するために、railsアプリケーションが使用するランダムな文字列です。

authentication_tokenが必要なのはなぜですか?

アプリまたはサイトをクロスサイトリクエストフォージェリから保護するため。

authentication_tokenをフォームに追加する方法は?

form_forタグを使用してフォームを生成している場合、authentication_tokenが自動的に追加されます<%= csrf_meta_tag %>。それ以外の場合は使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.