CSRF保護
概要
クロスサイトリクエストフォージェリは、認証されたユーザーに代わって不正なコマンドを実行する悪意のある悪用の一種です。幸い、Laravelはアプリケーションを クロスサイトリクエストフォージェリ (CSRF)攻撃から保護することを容易にします。
脆弱性の説明
クロスサイトリクエストフォージェリに精通していない場合、この脆弱性がどのように悪用されるかについて例を挙げて説明します。アプリケーションに/user/email
ルートがあり、認証されたユーザーのメールアドレスを変更するPOST
リクエストを受け入れるとします。ほとんどの場合、このルートは、ユーザーが使用する新しいメールアドレスを含むemail
入力フィールドを想定しています。
CSRF保護がない場合、悪意のあるWebサイトは、アプリケーションの/user/email
ルートを指し、悪意のあるユーザー独自のメールアドレスを送信するHTMLフォームを作成できます。
<form action="https://your-application.com/user/email" method="POST"></form> <script> document.forms[0].submit();</script>
悪意のあるWebサイトがページのロード時に自動的にフォームを送信する場合、悪意のあるユーザーはアプリケーションの何も知らないユーザーをWebサイトに誘導するだけで、そのユーザーのメールアドレスがアプリケーションで変更されます。
この脆弱性の防止策として、悪意のあるアプリケーションがアクセスできないシークレットセッション値に対するすべての着信POST
、PUT
、PATCH
、DELETE
リクエストを検査する必要があります。
CSRFリクエストを防止する
Laravelは、アプリケーションによって管理されているアクティブな ユーザーセッション ごとにCSRF「トークン」を自動的に生成します。このトークンは、認証されたユーザーが実際にアプリケーションに対する要求を作成した人であることを確認します。このトークンはユーザーのセッションに保存され、セッションが再生成されるたびに変化するため、悪意のあるアプリケーションはトークンにアクセスすることはできません。
現在のセッションのCSRFトークンは、リクエストのセッションまたはcsrf_token
ヘルパー関数からアクセスできます。
use Illuminate\Http\Request; Route::get('/token', function (Request $request) { $token = $request->session()->token(); $token = csrf_token(); // ...});
アプリケーションで「POST」、「PUT」、「PATCH」、「DELETE」HTMLフォームを定義する場合は、CSRF保護ミドルウェアが要求を検証できるように、隠れたCSRF_token
フィールドをフォームに含める必要があります。利便性のために、@csrf
Bladeディレクティブを使用して、隠れたトークン入力フィールドを生成できます。
<form method="POST" action="/profile"> @csrf <!-- Equivalent to... --> <input type="hidden" name="_token" value="{{ csrf_token() }}" /></form>
デフォルトでweb
ミドルウェアグループに含まれるIlluminate\Foundation\Http\Middleware\ValidateCsrfToken
ミドルウェアは、リクエスト入力内のトークンがセッションに格納されたトークンと一致することを自動的に検証します。これらの2つのトークンが一致した場合、認証されたユーザーが要求を開始したことがわかります。
CSRFトークンとSPA
LaravelをAPIバックエンドとして使用しているSPAを構築している場合、APIを使用した認証とCSRFの脆弱性に対する保護に関する情報については、Laravel Sanctumドキュメントを確認する必要があります。
CSRF保護からのURIの除外
場合によっては、一連のURIをCSRF保護から除外したい場合があります。たとえば、Stripeを使用して支払いを処理し、Webフックシステムを利用している場合、Stripeはルートに送信するCSRFトークンがわからいため、Stripe WebフックハンドラールートをCSRF保護から除外する必要があります。
通常、これらの種類のルートは、Laravelがroutes/web.php
ファイル内のすべてのルートに適用するweb
ミドルウェアグループの外部に配置する必要があります。ただし、アプリケーションのbootstrap/app.php
ファイルのvalidateCsrfTokens
メソッドにURIを提供することで、特定のルートを除外することもできます。
->withMiddleware(function (Middleware $middleware) { $middleware->validateCsrfTokens(except: [ 'stripe/*', 'http://example.com/foo/bar', 'http://example.com/foo/*', ]);})
利便上、テストの実行時は、すべてのルートに対してCSRFミドルウェアが自動的に無効になります。
X-CSRF-TOKEN
POSTパラメーターとしてCSRFトークンをチェックすることに加えて、デフォルトでweb
ミドルウェアグループに含まれるIlluminate\Foundation\Http\Middleware\ValidateCsrfToken
ミドルウェアは、X-CSRF-TOKEN
リクエストヘッダーもチェックします。たとえば、HTMLmeta
タグにトークンを格納できます
<meta name="csrf-token" content="{{ csrf_token() }}">
次に、jQueryのようなライブラリにすべてのリクエストヘッダーに自動的にトークンを追加するように指示できます。これにより、従来のJavaScriptテクノロジーを使用したAJAXベースのアプリケーションに、シンプルで便利なCSRF保護が提供されます
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }});
X-XSRF-TOKEN
Laravelは、フレームワークによって生成された各レスポンスとともに含まれる、暗号化されたXSRF-TOKEN
クッキーに現在のCSRFトークンを格納します。クッキー値を使用してX-XSRF-TOKEN
リクエストヘッダーを設定できます。
このクッキーは、AngularやAxiosなどの特定のJavaScriptフレームワークやライブラリが、同オリジンのリクエストに対して自動的にその値をX-XSRF-TOKEN
ヘッダーに配置するため、主に開発者の便宜として送信されます。
デフォルトでは、resources/js/bootstrap.js
ファイルにAxios HTTPライブラリが含まれており、X-XSRF-TOKEN
ヘッダーが自動的に送信されます。