RailsのAuthenticityTokenに関していくつかの問題が発生しています。
Authenticityトークンを本当に理解したいと思います。
このテーマに関する完全な情報源がありますか、それともここで詳細に説明するために時間を費やしますか?
RailsのAuthenticityTokenに関していくつかの問題が発生しています。
Authenticityトークンを本当に理解したいと思います。
このテーマに関する完全な情報源がありますか、それともここで詳細に説明するために時間を費やしますか?
何が起こるのですか
ユーザーがフォームを表示してリソースを作成、更新、または破棄すると、Rails アプリは random を作成し、authenticity_token
このトークンをセッションに保存して、フォームの非表示フィールドに配置します。ユーザーがフォームを送信すると、Rails は を探し、authenticity_token
それをセッションに保存されているものと比較し、それらが一致する場合はリクエストを続行できます。
なぜそれが起こるのか
認証トークンはセッションに保存されるため、クライアントはその値を知ることができません。これにより、Rails アプリ内でフォームを表示せずにフォームを Rails アプリに送信することができなくなります。サービス A を使用していて、サービスにログインしていて、すべて問題ないと想像してください。ここで、サービス B を利用していて、気に入った写真を見つけて、その写真を押して拡大表示したとします。ここで、サービス B に悪意のあるコードがあった場合、(ログインしている) サービス A にリクエストを送信し、http://serviceA.com/close_account
. これは、CSRF (クロス サイト リクエスト フォージェリ)として知られているものです。
サービス 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 サイトから送信されていることがわかるように設計されています。マシンのみが認識できる一意の識別子を使用して実行されるマシンから生成されるため、クロスサイト リクエスト フォージェリ攻撃の防止に役立ちます。
RailsがAJAXスクリプトへのアクセスを拒否することに単に問題がある場合は、次を使用できます
<%= form_authenticity_token %>
フォームを作成するときに正しいトークンを生成します。
詳細については、ドキュメントを参照してください。
Authenticity Tokenは、クロスサイトリクエストフォージェリ(CSRF)に対する対抗策です。CSRFとは何ですか?
これは、攻撃者がセッショントークンを知らなくてもセッションを乗っ取る可能性がある方法です。
シナリオ:
CSRFソリューション:
認証トークンは、クロスサイト リクエスト フォージェリ攻撃 (CSRF) を防ぐために使用されます。認証トークンを理解するには、まず CSRF 攻撃を理解する必要があります。
あなたが の作者だとしますbank.com
。あなたのサイトには、GET リクエストで別のアカウントに送金するために使用されるフォームがあります。
ハッカーは、HTTP リクエストをサーバーに送信してGET /transfer?amount=$1000000&account-to=999999
、
違う。ハッカーの攻撃は機能しません。サーバーは基本的に考えますか?
は?転送を開始しようとしているこの男は誰ですか。アカウントの所有者ではないことは確かです。
サーバーはこれをどのように認識していますか? session_id
リクエスタを認証する Cookieがないためです。
ユーザー名とパスワードでサインインすると、サーバーはsession_id
ブラウザーに Cookie を設定します。そうすれば、ユーザー名とパスワードで各リクエストを認証する必要がなくなります。ブラウザがsession_id
Cookie を送信すると、サーバーは次のことを認識します。
あ、ジョン・ドウです。彼は 2.5 分前に正常にサインインしました。彼は行く準備ができています。
ハッカーは次のように考えるかもしれません。
うーん。
session_id
通常の HTTP リクエストは機能しませんが、そのCookie を手に入れることができれば、私は成功するでしょう。
bank.com
ユーザーのブラウザには、ドメイン用に設定された一連の Cookie があります。ユーザーがドメインにリクエストを送信するたびにbank.com
、すべての Cookie が送信されます。session_id
クッキーを含みます。
したがって、ハッカーが自分のアカウントに送金する GET リクエストを作成するように仕向けることができれば、ハッカーは成功するでしょう。彼はどうやってあなたをだましてそうさせることができたのですか?クロス サイト リクエスト フォージェリを使用。
実際、それはかなり単純です。ハッカーは、あなたを自分の Web サイトにアクセスさせることができます。彼の Web サイトでは、次のイメージ タグを使用できます。
<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">
ユーザーのブラウザーがそのイメージ タグに遭遇すると、その URL に対して GET 要求を行います。リクエストは彼のブラウザから送信されるため、 に関連付けられているすべての Cookie が一緒に送信されますbank.com
。ユーザーが最近サインインした場合bank.com
、session_id
Cookie が設定され、サーバーは、ユーザーがアカウント 999999 に $1,000,000 を送金するつもりであると判断します。
まあ、危険なサイトにアクセスしないだけで大丈夫です。
それだけでは十分ではありません。誰かがその画像を Facebook に投稿し、それがあなたのウォールに表示されたらどうしますか? アクセスしているサイトに XSS 攻撃で挿入された場合はどうなりますか?
それはそう悪くはありません。GET リクエストのみが脆弱です。
違います。POST リクエストを送信するフォームを動的に生成できます。Rails Guide on Securityの例を次に示します。
<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
私のウェブサイト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
巨大な乱数であるため、推測することはできませんでした.
この防止手法はSynchronizer Token Patternと呼ばれます。
同一オリジン ポリシー
しかし、攻撃者が JavaScript を使用して 2 つのリクエストを作成した場合はどうなるでしょうか。1 つはトークンの読み取り、もう 1 つは送金です。
それを防ぐには、シンクロナイザー トークン パターンだけでは不十分です。
これは、 https ://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569# で説明したように、Same Origin ポリシーが助けになるところです。 72569
Rails がトークンを送信する方法
対象: Rails: How Does csrf_meta_tag Work?
基本的:
form_tag
GET フォームでない場合にフォームに非表示フィールドを追加するような HTML ヘルパー
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 または XSRF) 攻撃」を防ぐためAuthenticity Token
のRails の方法です。
簡単に言うと、Web アプリへの PUT / POST / DELETE (コンテンツを変更できるメソッド) 要求が、作成された Cookie にアクセスできるサード パーティ (攻撃者) からではなく、クライアントのブラウザーから行われるようにします。クライアント側で。
Authenticity Token
とても重要なので、Rails3.0以降では使用できます
<%= token_tag nil %>
作成する
<input name="authenticity_token" type="hidden" 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 などのべき等メソッドの場合に必要です。べき等メソッドはデータに影響を与えるためです。
必要な理由
邪悪な行為を防ぐために必要です。authentication_token はセッションに保存されます。リソースを作成または更新するために Web ページでフォームが作成されるたびに、認証トークンが非表示フィールドに保存され、フォームと共にサーバーに送信されます。アクションを実行する前に、ユーザーが送信したauthenticity_tokenが
authenticity_token
セッションに保存されているものと照合されます。同じである場合authenticity_token
、プロセスは続行されます。それ以外の場合、アクションは実行されません。
authentication_token とは何ですか?
これは、ユーザーが別のアプリやサイトからではなく、アプリ ページからアクションを要求または実行していることを確認するために、Rails アプリケーションによって使用されるランダムな文字列です。
なぜ authentication_token が必要なのですか?
アプリやサイトをクロスサイト リクエスト フォージェリから保護するため。
authentication_token をフォームに追加するには?
form_for タグを使用してフォームを生成している場合、authentication_token が自動的に追加されます<%= csrf_meta_tag %>
。