クロスサイトリクエストフォージェリ(CSRF)
Webサイトにスクリプトや自動転送(HTTPリダイレクト)を仕込むことによって、利用者に意図せず別のWebサイト上で何らかの操作(掲示板への書き込みや銀行口座への送金など)を行わせる攻撃手法のことをいいます。
CSRFの脆弱性が存在すると以下のような被害を被る可能性があります。
①利用者のアカウントによる物品の購入
②利用者の退会処理
③利用者のアカウントによる掲示板への書き込み
④利用者のパスワードやメールアドレスが変更
CSRF脆弱性の影響は「重要な処理」の悪用に限られるため、CSRFの脆弱性を個人情報の取得等に用いることはできません。
CSRFの攻撃例
例えば、利用者が罠サイトを閲覧することによってパスワードが変更されてしまう場合
①利用者がexample.jpにログインしている
②攻撃者は罠を作成
③利用者が罠を閲覧する
④罠のJavaScriptによる、被害者のブラウザ上で攻撃対象サイトに対し、新しいパスワードabcdefがPOSTメソッドにより送信される
⑤パスワードが変更される
CSRFの対策
CSRF攻撃を防ぐには、「重要な処理」に対するリクエストが利用者の意図によるものかどうかを確認することが必要になります。
このためCSRF対策が以下の2点です。
①CSRF対策の必要なページを区別する
②正規利用者の意図したリクエストを区別できるように実装する
CSRF対策の必要なページを区別する
CSRF対策はすべてのページに行う必要はありません。対策に必要なページは、他のサイトから勝手に実行されては困るようなページです。例えば、ECサイトの物品購入ページや、パスワード変更など個人情報の編集確定画面などです。
CSRFの対策としては、まず実装するWebアプリケーションのどのページに脆弱性対策が必要なのか設計段階で明らかにすることです。
例えば、機能一覧を紙に記入し、CSRFの対策が必要なページを色分けすると良いと思います。
商品ページ=>認証=>カートに追加=>購入確認=>購入確定
この中だと最後の購入確定がCSRFの対策が必要です。
正規利用者の意図したリクエストを区別できるように実装
CSRF対策で必要なことは、正規利用者の意図したリクエストなのかどうかということです。
意図したリクエストとは、利用者が対象のアプリケーション上で「実行」ボタンなどを押して、「重要な処理」のリクエストを発行することです。
正規のリクエストかどうかを判断する方法は3種類あります。
①秘密情報の埋め込み
②パスワードの再入力
③Refererのチェック
秘密情報の埋め込み
登録画面や注文確定画面などのCSRF攻撃への対策が必要なページに対して、第三者の不正利用者が知り得ない秘密情報を要求するようにすれば、不正リクエストによる重要な処理が実行されることはありません。このような目的で使用される秘密情報のことをトークンといいます。
パスワードの再入力
こちらは文字通り重要な処理が確定する前に、再度パスワードを入力してもらいます。これはCSRF対策の他にも物品の購入などに先立って、利用者の意思の念押しをしたり、共用のPCにおいて正規の利用者以外の利用者が、重要な処理を実行するのを防いだりする効果があります。
CSRFの攻撃例として、とりあげたパスワード変更ページにも現在のパスワードを再入力させることによりCSRF攻撃を防ぐことが可能です。
RailsでのCSRF対策方法
Rails側できちんと対策を行ってくれています。基本的には開発者はなにもしなくても大丈夫です。
例として、RailsでのCSRF対策
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception #追加部分
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :nickname
end
end
protect_from_forgery with: :exception
これがRailsアプリケーション内でCSRF対策を行うというという命令になります。こちらをすべてのコントローラの親であるapplication_controller.rbに記述することによって、その子コントローラすべてに先ほど説明したようなCSRF対策をRails側で行ってくれます。
具体的には、まずサイトのHTMLに一意のトークンを埋め込みます。これと同じトークンを、セッションcookie(クッキー)にも保存しています。ユーザーがPOSTリクエストを送信すると、HTMLに埋められているCSRFトークンも一緒に送信されます。あとは、サーバ側でページのトークンとセッション内のトークンを比較し、両者が一致することを確認したらリクエストを受け付けます。