25年度入社の斎藤です。
今回は、Webアプリケーションに対する代表的な攻撃手法であるCSRF(クロスサイトリクエストフォージェリ)について、概要を簡単にまとめ、CSRF攻撃に対する一般的な対策とLaravelでどのように対策が行われているのかについて説明しようと思います。
CSRFとは
CSRF(クロスサイトリクエストフォージェリー)は、Webアプリでログイン状態を保持している利用者に、ユーザーの意図しない不正なリクエストを送信させる攻撃手法です。
正規のリクエスト方法とは異なるリクエストが受け入れられてしまうようなwebアプリの脆弱性が存在する場合に被害にあう可能性があります。
以下に具体的なCSRF攻撃手法の被害までの基本的な流れを銀行webアプリを例に説明します。
【前提条件】
・正規の銀行webサイト(例:https://bank.com)が存在し、送金機能をもつ
・CSRF対策(CSRFトークン)が実装されておらず脆弱性が存在する
※CSRFトークンについては後述
ステップ1:ユーザーが正規サイトにログイン
ユーザーが銀行サイト(bank.com)に正しい方法でログインします。
この際、Cookieが保存され、bank.comへのリクエスト時にはユーザーを識別するために自動的に送信されます。
ステップ2:攻撃者が作成した不正なサイトにユーザーがアクセスする
以下のような方法で不正なサイトにアクセスさせます。
・メールに記載されたリンク
・SNSの広告クリック
・掲示板に貼られたリンク
・他のサイトに埋め込まれた広告
など
ステップ3:不正なサイトのスクリプトが自動実行される
以下のフォームでは、正規の銀行webサイトに対して、攻撃者の口座(to_account)と送金金額(amount)を指定しています。

CSRF対策
主なCSRF対策方法として、CSRFトークンを使用することが挙げられます。CSRFトークンは正規のページを表示したときにだけ発行される予測不可能なランダムな値です。
このランダムな値をサーバーが生成してHTMLのFormに埋め込むことで、Form送信時にFormデータに合わせてCSRFトークンをserverへ送信し、フォームの正当性を担保することができます。
※CSRF攻撃では攻撃者はトークンを読み取れません
Laravel(Blade)でのCSRF対策
フォームタグ内に @CSRF を記述することで、Laravelが自動的にフォームに対してCSRFトークンを埋め込んでくれます。

※web.php(ルーティングファイル)では、@CSRFの付与されていないPOST/PUT/PATCH/DELETEリクエスト はエラーで弾かれるようになっています
jQueryのAjax通信でのCSRF対策
Ajax通信でのリクエストにもCSRFトークンを埋め込むことができます。
まず以下のようにBladeのheadタグ内にmataタグを用いてCSRFトークンを埋め込みます。

次にJavaScriptのjQuery.ajaxSetupメソッドに以下の記述を追加することで、metaタグからCSRFトークンを取得して、Ajaxリクエストに含めることができます。
※$.ajaxSetupはajax通信に関連するデフォルト値を変更するメソッド

最後に
これまで、セキュリティ攻撃といえば不正なサイトに誘導する、webサイト自体に対して悪意ある改変を行うといったイメージを持っていました。
CSRF攻撃はそれとは全く異なるアプローチで、攻撃者が自分のサイトから正規サイトへリクエストを送信し、ブラウザが自動的にCookieを付与してしまうことで、ユーザーの意図しない操作が実行されてしまうという「正規のフォーム外から攻撃する」という発想は、自分にとって全く考えたことのない視点であったので、非常に興味深く感じました。
今回の話は以上です。
ありがとうございました。
参考
安全なウェブサイトの作り方 – 1.6 CSRF(クロスサイト・リクエスト・フォージェリ)https://www.ipa.go.jp/security/vuln/websecurity/csrf.html
Readouble Laravel 9.x CSRF保護
https://readouble.com/laravel/9.x/ja/csrf.html
「CSRFって美味しいの?」←ハンズオンで実装して理解してみたhttps://qiita.com/Naughty1029/items/c606d4f12e994b46ba58
