0
0

More than 1 year has passed since last update.

CSRFに関する学習メモ

Last updated at Posted at 2022-11-06

学習背景

現職でRailsを使用しており、他の方が書かれたコードにprotect_from_forgeryという記述がありました。protect_from_forgeryを調べてみると、CSRF対策のためと記載があり、そういえばCSRFってなんでしたっけ?ということで調べてみました。

CSRFについて

CSRFとはクロスサイト・リクエスト・フォージェリの略で、フォージェリとは「偽造品」という意味があります。

CSRFについてウィキペディアで以下のように説明されています。

CSRF脆弱性とは以下のような攻撃(CSRF攻撃)を可能にする脆弱性を指す[1]:攻撃者はブラウザなどのユーザ・クライアントを騙し、意図しないリクエスト(たとえばHTTPリクエスト)をWebサーバに送信させる。

例えば、ショッピングサイトにログイン状態で悪意のあるユーザが作ったサイトをクッリクすると、ショッピングサイトにログインしたユーザのメールアドレスやパスワードを悪意のあるユーザが指定したものに変更されてしまいます。

「悪意のあるユーザが作ったサイト」とは、どんなサイトなんだろう??

例えば、ショッピングサイトでパスワードを変える際には以下の流れがあったとします。
①パスワード変更画面で新しいパスワードを変更する。(簡単ですが、以下のようなイメージです。。)

image.png

②パスワードを変更したことをユーザに通知する画面((こちらも簡単ですが、イメージです。。))

image.png

上記のようなショッピングサイトにログイン中のユーザが悪意のあるサイトをクリックすると、上記サイトのパスワードを変更されてしまうサイトです。例えば以下のようなコードです。

<body onload="document.forms[0].submit()">
<form action="http://hogehoge/45" method="POST">
<input type="hidden" name="pwd" value="hogehoge">
</body>

以下のJavascriptのコードで悪意のあるページを開いた瞬間にフォームの中身がサーバ側に送信されてしまいます。

<body onload="document.forms[0].submit()">

送信先は適当にhttp://hogehoge/45とショッピングサイトのパスワードを変更する処理に向けたURLを指定します。

<form action="http://hogehoge/45" method="POST">

value="hogehoge"で悪意のあるユーザが決めたパスワードhogehogeに変更されます。

<input type="hidden" name="pwd" value="hogehoge">

CSRF対策

3点あります。
①パスワード変更画面で新しいパスワードを送信する際にトークンを発行して、悪意のあるサイトからの送信ではないかを確認する。
②パスワードを変更する前にユーザIDとパスワードを入力させてから、パスワード変更を可能にさせる。
③パスワード変更画面から送られてくるリクエストURLをコントローラー側で見て、そのURLが悪意のあるサイトからのURLではないかをチェックする。正規ユーザがパスワード変更画面から変更したものであるかをチェックする。

①についてですが、パスワード変更画面に実装するのは、例えば以下のようなコードです。

<form action="changepassword" method= "post">
  新しいパスワード<input name="pwd" type="password">
  <input type="hidden" name="authenticity_token" value="<token_value>">
</form>

value="<token_value>"でトークンをコントローラー側に送信して、コントローラー側でビュー側で送られてきたトークンをチェックすることで、悪意のあるユーザによるパスワード変更を防ぎます。

<input type="hidden" name="authenticity_token" value="<token_value>">

今回疑問に思ったきっかけであるprotect_from_forgeryは①のCSRF対策に該当します。
Railsセキュリティガイドを読むと、protect_from_forgeryはデフォルトで設定されているとのことです。また、コントローラー側にprotect_from_forgeryの記載不要だけでなく、ビュー側にもトークンを発行する処理が不要とも書かれてあり、開発者にとってはとてもありがたいです。

以下の1行コードはアプリケーションのコントローラに追加するものであり、Railsで新規作成したアプリケーションにはこのコードがデフォルトで含まれます。

protect_from_forgery with: :exception
このコードがあると、Railsで生成されるすべてのフォームとAjaxリクエストにセキュリティトークンが自動的に含まれます。

感想

Railsのようなフレームワーク側でセキュリティ対策してくれているのはありがたいな、と思いました。また、他のセキュリティ対策についてもRails側でどのような対策をされているのかについても深く理解していきたいと思いました。 

参考文献

この記事は以下の情報を参考にして執筆しました。

0
0
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
0
0