コンテンツにスキップ

CSRF保護

概要

クロスサイトリクエストフォージェリは、認証されたユーザーに代わって不正なコマンドを実行する悪意のある悪用の一種です。幸い、Laravelはアプリケーションを クロスサイトリクエストフォージェリ (CSRF)攻撃から保護することを容易にします。

脆弱性の説明

クロスサイトリクエストフォージェリに精通していない場合、この脆弱性がどのように悪用されるかについて例を挙げて説明します。アプリケーションに/user/emailルートがあり、認証されたユーザーのメールアドレスを変更するPOSTリクエストを受け入れるとします。ほとんどの場合、このルートは、ユーザーが使用する新しいメールアドレスを含むemail入力フィールドを想定しています。

CSRF保護がない場合、悪意のあるWebサイトは、アプリケーションの/user/emailルートを指し、悪意のあるユーザー独自のメールアドレスを送信するHTMLフォームを作成できます。

<form action="https://your-application.com/user/email" method="POST">
<input type="email" value="[email protected]">
</form>
 
<script>
document.forms[0].submit();
</script>

悪意のあるWebサイトがページのロード時に自動的にフォームを送信する場合、悪意のあるユーザーはアプリケーションの何も知らないユーザーをWebサイトに誘導するだけで、そのユーザーのメールアドレスがアプリケーションで変更されます。

この脆弱性の防止策として、悪意のあるアプリケーションがアクセスできないシークレットセッション値に対するすべての着信POSTPUTPATCHDELETEリクエストを検査する必要があります。

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/*',
]);
})
lightbulb

利便上、テストの実行時は、すべてのルートに対して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ヘッダーに配置するため、主に開発者の便宜として送信されます。

lightbulb

デフォルトでは、resources/js/bootstrap.jsファイルにAxios HTTPライブラリが含まれており、X-XSRF-TOKENヘッダーが自動的に送信されます。