こんにちは、hachi8833です。
BigBinaryシリーズ、今回もRails 5から導入された機能についての翻訳記事をお届けいたします。
元記事
確認に使った環境
- Railsバージョン: 5.0.2(5.0-stable)
- Rubyバージョン: 2.4.1p111
Rails 5の新機能: フォームごとに異なるCSRFトークンを受け取れるようになった(翻訳)
BigBinaryの以前の記事で、Rails 4でCSRF攻撃を防ぐための手順を詳しく紹介しました。本記事を詳しく理解するためにはこの記事もご覧ください。
Rails 4のCSRF保護は、ネストしたフォームで効かないことがある
Rails 4の典型的なフォームのコードを以下に示します(訳注: valueの< >
はプレースホルダを表します)。
<form method= "post" action="/money_transfer">
<input type="hidden" name="authenticity_token" value="<token_value>">
</form>
攻撃者がコードを注入すると、RailsでJavaScriptを使って生成したフォームの外側に、以下のように別のフォームタグが追加される可能性があります。
<form method="post" action="http://www.fraud.com/fraud">
<form method= "post" action="/money_transfer">
<input type="hidden" name="authenticity_token" value="<token_value>">
</form>
</form>
HTMLの仕様では、フォームのネストは許されていません。
フォームのネストが禁止されているため、ブラウザは最も外側(最上位)のフォームのみを受け付けます。上のコードでは、攻撃者が捏造したフォームがネストの最上位に置かれています。このフォームが送信されると、内側にある「authenticity_token」も送信されます。Railsはこれを正当であると認識し、それによって攻撃者がサイトをハックできてしまいます。
Rails 5での修正: フォームでカスタムトークンを生成するようになった
Rails 5では、CSRFトークンをフォームごとに追加できるようになりました(#22275)。各CSRFトークンは、それを含むフォームに対応するメソッドやアクションに対してのみ有効になります。
コントローラに以下のようにself.per_form_csrf_tokens = true
を追加することで、コントローラのフォームタグごとにメソッドやアクション固有の認証トークンが追加されます。
class UsersController < ApplicationController
self.per_form_csrf_tokens = true
end
このコードを各コントローラに追加して回るのは面倒なので、Railsの初期化設定に以下の記述を追加して、全コントローラで設定を有効にすることもできます。
# config/application.rb
Rails.configuration.action_controller.per_form_csrf_tokens = true
これにより、アプリケーションのフォームタグごとにメソッドやアクション固有の認証トークンが追加されます。トークンが追加された後のコードは以下のようになります。
<form method= "post" action="/money_transfer">
<input type="hidden" name="authenticity_token" value="<money_transfer_post_action_token>">
</form>
ここで使われている認証トークンは、money_transfer
アクションとpost
メソッド固有です。攻撃者がこの認証トークンを取り出したとしても、攻撃はmoney_transfer
アクションへのpost
のみに限定されます。
関連記事(Rail 5新機能)
- [Rails 5] developmentモードのアセットログはデフォルトでオフになる(翻訳)
- [Rails 5] rails dev:cacheコマンドでdevelopmentモードでのキャッシュを簡単にオン・オフできる
- [Rails 5] コントローラの制約を受けずに任意のビューテンプレートをレンダリングする
- [Rails 5] rakeタスクがrailsコマンドでもできるようになった
- [Rails 5] Rails 5の新フレームワークデフォルト設定ファイルでアップグレード作業を軽減する
- [Rails 5] マイグレーション時にデータベースのカラムにコメントを追加する