67
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

おにぎり万太郎Advent Calendar 2019

Day 18

RailsのCSRF対策について

Last updated at Posted at 2019-12-17

CSRFとは

  • Cross Site Request Forgeriesの頭文字をとってCSRF(シーサーフと読むらしい)
  • Webアプリケーションにおける脆弱性の1種
  • ざっくりいうと「サイトのログイン状態が保持されている状態で悪意のあるリンクを踏むと、意図しないリクエストを送ってしまう」というもの
  • 以下具体例
    • 利用者Aがサイトにログインする
      • ログインに成功した時点でRailsアプリはAが使ってるブラウザにセッションクッキーを保存する
      • このセッションクッキーはそれ以降すべてのHTTPリクエストと一緒に送信される
      • Railsはこのセッションクッキーの値を調べることで、ログイン済みかどうかを判断する
    • 攻撃者Xが他のサイトに悪意のあるリンクを仕込む
      • ユーザー認証はブラウザに保存されているセッションクッキーで突破することを前提
    • 利用者Aが攻撃者Xが仕込んだリンクを踏む
      • セッションが切れていなければ、アプリ側はログイン済みだと判断する(他のサイトからのリクエストでもセッションクッキーは送信される)
      • もしアプリ側でCSRF対策がされていなければそのリクエストは有効なリクエストとして扱われるため、利用者Aが意図しない挙動をしてしまう
        • するつもりのない投稿, データの削除, 課金処理 etc,,,

RailsにおけるCSRF対策(protect_from_forgeryメソッド)

どうやって対策してるか

  • RailsではCSRF対策として「セキュリティトークンを仕込む」という方法を採用している
    • Railsアプリ内からの(GET以外の)リクエストにはセキュリティトークンを仕込み、それを確認することでアプリ内からの有効なリクエストかどうかを判断する
  • それをよしなにやってくれているのがprotect_from_forgeryメソッドと、Railsが提供するformのヘルパー
  • Railsが提供するform_withform_forなどのヘルパーを使うと、自動でセキュリティトークン(authenticity_token)を仕込んでくれる
  • protect_from_forgeryメソッドを記述すると、Rails側で正しいauthenticity_tokenがセットされるかどうかをチェックしてくれるので、CSRFを防ぐことができる

具体的な設定方法

  • protect_from_forgeryをcontrollerに指定し、formにはヘルパーを使うだけ
    • Rails5.2以降ではActionController::Base内で有効になっているため、デフォルトの設定でよければ自分で記述する必要はない
    • それ以前のバージョンだとrails newした時点でApplicationControllerに記述されている

protect_from_forgeryのオプション

  • prependオプション

    • デフォルトではfalseになっている
    • prepend: trueを指定すると記述した場所に関わらずに常に処理の最初に実行される
  • withオプション

    • セキュリティトークンが一致しなかった場合の挙動を指定するオプション
    • デフォルトは:null_session(セッションを空にする)
    • :execption(例外を起こす)を指定している状態でトークンが一致しないとActionController::InvalidAuthenticityTokenエラーが起こる
  • オプションについて詳しくはこのサイトを参照

テスト環境でprotect_from_forgeryを有効にするには

RSpecでの例
before do
  # 明示的にallow_forgery_protectionを有効にする
  ActionController::Base.allow_forgery_protection = true
end

after do
  # 他のテストケースに影響を与えないために無効にしておく
  ActionController::Base.allow_forgery_protection = false
end

参考サイト

67
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?