CSRFについて

#はじめに
Webアプリケーションには、利用者自らの操作では取り消しのできない重要な処理があります。ここでいう「重要な処理」とはECサイトでのクレジットカードでの決済やメールの送信、パスワードの変更などのことをいいます。
こういった重要な処理の過程で不備があると、クロスサイトリクエストフォージェリ(以下CSRFと省略)の脆弱性が生じる場合があります。CSRFは「シーサーフ」もしくは「シーエスアールエフ」と呼ばれます。

##CSRF(クロスサイトリクエストフォージェリ)
本章では掲示板への投稿やメールの送信、ECサイトでの商品購入など本来外部より実行されてはいけない重要な処理を、なんらかの攻撃手法を用いて実行させてしまうという攻撃手法であるCSRF(クロスサイトリクエストフォージェリ)の概要と対策方法を学習していきます。

##CSRFとは
Webサイトにスクリプトや自動転送（HTTPリダイレクト）を仕込むことによって、利用者に意図せず別のWebサイト上で何らかの操作（掲示板への書き込みや銀行口座への送金など）を行わせる攻撃手法のことをいいます。
CSRFの脆弱性が存在すると以下のような被害を被る可能性があります。

利用者のアカウントによる物品の購入
利用者の退会処理
利用者のアカウントによる掲示板への書き込み
利用者のパスワードやメールアドレスが変更
CSRF脆弱性の影響は「重要な処理」の悪用に限られるため、CSRFの脆弱性を個人情報の取得等に用いることはできません。

##CSRFの攻撃例
利用者が罠サイトを閲覧することによってパスワードが変更されてしまう例

利用者がexample.jpにログインしている
攻撃者は罠を作成
利用者が罠を閲覧する
罠のJavaScriptによる、被害者のブラウザ上で攻撃対象サイトに対し、新しいパスワードabcdefがPOSTメソッドにより送信される
パスワードが変更される

![Qiita](https://tech-master.s3.amazonaws.com/uploads/curriculums//be60f47f84d234c3b1e7581f7e5564c0.jpeg "Qiita")

##CSRFの対策
##一般的な対策方法
CSRF攻撃を防ぐには、「重要な処理」に対するリクエストが利用者の意図によるものかどうかを確認することが必要
このためCSRF対策としては、以下の2点が考えられる。

CSRF対策の必要なページを区別する
正規利用者の意図したリクエストを区別できるように実装する

###CSRF対策の必要なページを区別する
CSRF対策はすべてのページに行う必要はありません。むしろ、対策の必要がないページの方が多いのです。対策に必要なページは、他のサイトから勝手に実行されては困るようなページです。例えば、ECサイトの物品購入ページや、パスワード変更など個人情報の編集確定画面などが挙げられます。
CSRFの対策としては、まず実装するWebアプリケーションのどのページに脆弱性対策が必要なのか設計段階で明らかにすることです。
以下の図のように、機能一覧の中でCSRFの対策が必要なページを色分けすると良いと思います。

![Qiita](https://tech-master.s3.amazonaws.com/uploads/curriculums//e2212a3142a9f3d64153bd755af11993.jpeg "Qiita")

###正規利用者の意図したリクエストを区別できるように実装する
CSRF対策で必要なことは、正規利用者の意図したリクエストなのかどうかということです。
ここでの意図したリクエストとは、利用者が対象のアプリケーション上で「実行」ボタンなどを押して、「重要な処理」のリクエストを発行することをいいます。
正規のリクエストかどうかを判断する方法は3種類あります。

秘密情報の埋め込み
・パスワードの再入力
・Refererのチェック
・Refererによるチェックは少し難しいので、上の二つについて説明します。

####秘密情報の埋め込み
登録画面や注文確定画面などのCSRF攻撃への対策が必要なページに対して、第三者の不正利用者が知り得ない秘密情報を要求するようにすれば、不正リクエストによる重要な処理が実行されることはありません。このような目的で使用される秘密情報のことをトークンといいます。

![Qiita](https://tech-master.s3.amazonaws.com/uploads/curriculums//838a8668f06823ba649eefd8b5906661.jpeg "Qiita")

####パスワードの再入力
こちらは文字通り重要な処理が確定する前に、再度パスワードを入力してもらいます。これはCSRF対策の他にも物品の購入などに先立って、利用者の意思の念押しをしたり、共用のPCにおいて正規の利用者以外の利用者が、重要な処理を実行するのを防いだりする効果があります。
CSRFの攻撃例として、とりあげたパスワード変更ページにも現在のパスワードを再入力させることによりCSRF攻撃を防ぐことが可能です。
しかし、対策が必要なページ以外でパスワードの再入力を求めるページが複数あると煩雑なアプリケーションになってしまうため、注意が必要です。

##RailsでのCSRF対策方法
それではRailsではどのようにCSRF対策を行っていけばいいのでしょうか。
実は、Rails側できちんと対策を行ってくれています。基本的には開発者はなにもしなくても大丈夫です。
それでは実際にRailsがどのようにCSRF対策を行っているか見ていきましょう。

ChatSpaceのapplication_controller.rbを開いてみましょう。

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# 省略
  protect_from_forgery with: :exception
# 省略
end
```

protect_from_forgery with: :exceptionという記述があるかと思います。これがRailsアプリケーション内でCSRF対策を行うというという命令になります。
こちらをすべてのコントローラの親であるapplication_controller.rbに記述することによって、その子コントローラすべてに先ほど説明したようなCSRF対策をRails側で行ってくれます。
なおRails5.2以降では、ActionController :: Baseで、はじめからCSRF対策機能が有効になっているので、application_controller.rbにこの記述がなくなります。

CSRF対策としてどのような事が行われているかというと、まずサイトのHTMLに一意のトークンを埋め込みます。これと同じトークンを、セッションcookie(クッキー)にも保存しています。ユーザーがPOSTリクエストを送信すると、HTMLに埋められているCSRFトークンも一緒に送信されます。あとは、サーバ側でページのトークンとセッション内のトークンを比較し、両者が一致することを確認したらリクエストを受け付けます。

##まとめ
CSRFとはアプリケーション内で重要な処理が行われる場所で発生する攻撃手法である
CSRFを防ぐにはトークンを埋め込んだり、パスワードを再入力させたり、ページ遷移の際正規利用者しか知り得ない情報を用いることが有効
RailsでCSRF対策を行う際はコントローラ内にprotect_from_forgeryメソッドを記述する