[Rails 5] フォームごとに異なるCSRFトークンを受け取れるようになった(翻訳)

こんにちは、hachi8833です。
BigBinaryシリーズ、今回もRails 5から導入された機能についての翻訳記事をお届けいたします。

元記事

確認に使った環境

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新機能)

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833 コボラー、ITコンサル、ローカライズ業界を経てなぜかWeb開発者志願。 これまでにRuby on Rails チュートリアルの大半、Railsガイドのほぼすべてを翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ