回答:
何が起こるのですか
ユーザーがフォームを表示してリソースを作成、更新、または破棄すると、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によるコメントを確認してください。彼は私がここで行ったよりも良い方法でそれを説明しています。
認証トークンは、フォームがWebサイトから送信されていることがわかるように設計されています。それはあなたのマシンだけが知ることができるユニークな識別子でそれが走っているマシンから生成され、クロスサイトリクエストフォージェリ攻撃を防ぐのを助けます。
AJAXスクリプトアクセスを拒否するレールに単に問題がある場合は、
<%= form_authenticity_token %>
フォームの作成時に正しいトークンを生成します。
詳細については、ドキュメントをご覧ください。
Authenticity Tokenは、Cross-Site Request Forgery(CSRF)への対策です。CSRFとは何ですか?
これは、攻撃者がセッショントークンを知らなくてもセッションを乗っ取る可能性がある方法です。
シナリオ:
CSRFソリューション:
防止される最小限の攻撃の例: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トークンが機能します。
したがって、本物のブラウザのフォームは次のようになります。
<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はまた、古いキャッシュフラグメントの形式でトークンを更新しようとします。
その他の予防アプローチ
X-Requested-With
:
Origin
ヘッダーの値を確認します。https://security.stackexchange.com/questions/91165/why-is-the-synchronizer-token-pattern-preferred-over-the-origin-header-check-to認証トークンは、クロスサイトリクエストフォージェリ攻撃(CSRF)を防ぐために使用されます。認証トークンを理解するには、まずCSRF攻撃を理解する必要があります。
あなたがの作者であるとしますbank.com
。GETリクエストで別のアカウントに送金するために使用するフォームがサイトにあります。
ハッカーは、サーバーにHTTPリクエストを送信してGET /transfer?amount=$1000000&account-to=999999
、と言ってもいいでしょう?
違う。ハッカーの攻撃は機能しません。サーバーは基本的に考えますか?
えっ?転送を開始しようとしているこの男は誰ですか。それは確かにアカウントの所有者ではありません。
サーバーはどのようにこれを知っていますか?ないのでsession_id
リクエスタを認証するCookieです。
ユーザー名とパスワードを使用してサインインすると、サーバーはsession_id
ブラウザーにCookieを設定します。そうすれば、ユーザー名とパスワードを使用して各リクエストを認証する必要がなくなります。ブラウザがsession_id
Cookieを送信すると、サーバーは次のことを認識します。
ああ、それはジョン・ドーです。彼は2.5分前に正常にサインインしました。彼はいいです。
ハッカーは次のように考えるかもしれません:
うーん。通常のHTTPリクエストは機能しませんが、もしその
session_id
Cookieを手に入れることができれば、私は金色になるでしょう。
ユーザーのブラウザには、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_id
Cookieが設定され、サーバーはユーザーが$ 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="✓" />
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Form contents
</form>
特に、以下が生成されます。
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
CSRF攻撃から保護するために、Railsがリクエストと共に送信された認証トークンを認識しない場合、リクエストは安全であるとは見なされません。
攻撃者はどのようにしてこのトークンが何であるかを知っているはずですか?フォームが生成されるたびに、異なる値がランダムに生成されます。
クロスサイトスクリプティング(XSS)攻撃-その方法です。しかし、それは別の日に別の脆弱性です。
「クロスサイトリクエストフォージェリ(CSRFまたはXSRF)攻撃」Authenticity Token
を防ぐため のis railsメソッド。
簡単に言うと、WebアプリへのPUT / POST / DELETE(コンテンツを変更できるメソッド)リクエストが、作成されたCookieにアクセスできるサードパーティ(攻撃者)からではなく、クライアントのブラウザから行われるようにします。クライアント側で。
それAuthenticity Token
はとても重要なので、Rails 3.0 以降では
<%= token_tag nil %>
作成する
<input name="authenticity_token" type="hidden" value="token_value">
どこでも
XSS
悪質な目的ではなく、ログインページで実行しようとしていたが、事前に入力されたユーザー名で新しいセッションを作成しようとしていた。今、私はただ使うことができることを知っていますvalue="token_value"
。
Authenticity Tokenメカニズムは、同じクライアントから複数の同時要求がある場合に競合状態を引き起こす可能性があることに注意してください。この状況では、サーバーは1つしか存在しないはずの複数の認証トークンを生成でき、フォームで以前のトークンを受け取ったクライアントは、セッションCookieトークンが上書きされているため、次のリクエストで失敗します。この問題についての説明があり、完全に簡単な解決策はありません:http : //www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/
メソッドauthenticity_token
必要な場所
authenticity_token
べき等メソッドはデータに影響を与えるため、post、put、deleteなどのべき等メソッドの場合は必須です。
必要な理由
邪悪な行為を防ぐ必要があります。authenticity_tokenはセッションに保存されます。リソースを作成または更新するためにWebページでフォームが作成されると、認証トークンが非表示フィールドに保存され、サーバー上のフォームとともに送信されます。アクションを実行する前に、ユーザーが送信したauthenticity_tokenが
authenticity_token
セッションに格納されているかどうかがクロスチェックされます。authenticity_token
同じ場合、プロセスは続行されます。それ以外の場合、アクションは実行されません。
authentication_tokenとは何ですか?
これは、ユーザーが別のアプリやサイトからではなく、アプリのページからアクションをリクエストまたは実行していることを確認するために、railsアプリケーションが使用するランダムな文字列です。
authentication_tokenが必要なのはなぜですか?
アプリまたはサイトをクロスサイトリクエストフォージェリから保護するため。
authentication_tokenをフォームに追加する方法は?
form_forタグを使用してフォームを生成している場合、authentication_tokenが自動的に追加されます<%= csrf_meta_tag %>
。それ以外の場合は使用できます。