CSRF 保護

  • はじめに
  • CSRF リクエストの防止
    • URI の除外
  • X-CSRF トークン

  • X-XSRF- … 続きを読むToken

Introduction

クロスサイトリクエストフォージェリーは、認証されたユーザーの代わりに未承認のコマンドが実行される悪質なエクスプロイトの一種である。 ありがたいことに、Laravel はクロスサイトリクエストフォージェリ (CSRF) 攻撃からアプリケーションを簡単に保護できます。

脆弱性の説明

クロスサイトリクエストフォージェリに慣れていない方のために、この脆弱性が悪用される方法の例を説明しましょう。 あなたのアプリケーションに、認証されたユーザーの電子メールアドレスを変更するための POST リクエストを受け入れる /user/email ルート があるとします。 ほとんどの場合、このルートは、ユーザーが使い始めたい電子メールアドレスを含む email 入力フィールドを期待しています。

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

<form action="https://your-application.com/user/email" method="POST"> <input type="email" value=""></form><script> document.forms.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(); // ...});

アプリケーションで HTML フォームを定義するときはいつでも、CSRF 保護ミドルウェアがリクエストを検証できるように、フォームに CSRF _token フィールドを隠します。 便宜上、@csrf Blade ディレクティブを使用して、隠しトークン入力フィールドを生成できます。

<form method="POST" action="/profile"> @csrf <!-- Equivalent to... --> <input type="hidden" name="_token" value="{{ csrf_token() }}" /></form>

web ミドルウェア グループにデフォルトで含まれている App\Http\Middleware\VerifyCsrfToken ミドルウェアは、リクエスト入力内のトークンがセッションに保存されているトークンと一致するか自動的に検証を行います。

CSRF トークン & SPA

API バックエンドとして Laravel を利用する SPA を構築する場合は、Laravel Sanctum のドキュメントを参照して API での認証と CSRF 脆弱性に対する保護に関する情報を入手する必要があります。

CSRF 保護からの URI の除外

場合によっては、CSRF 保護から URI のセットを除外したいことがあります。 たとえば、Stripe を使用して支払いを処理し、その Webhook システムを利用している場合、Stripe はルートに送信する CSRF トークンを知らないため、CSRF 保護から Stripe Webhook ハンドラ ルートを除外する必要があります。

通常、これらの種類のルートを、App\Providers\RouteServiceProviderroutes/web.php ファイル内のすべてのルートに適用するミドルウェア グループ web 以外の場所に配置すべきです。 しかし、VerifyCsrfTokenミドルウェアの $except プロパティにそれらの URI を追加することによって、ルートを除外することもできます:

<?phpnamespace App\Http\Middleware;use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;class VerifyCsrfToken extends Middleware{ /** * The URIs that should be excluded from CSRF verification. * * @var array */ protected $except = ;}

{tip}. 利便性のため、テストを実行するとき、CSRF ミドルウェアはすべてのルートに対して自動的に無効になります。

X-CSRF-TOKEN

POSTパラメーターとして CSRF トークンをチェックすることに加えて、App\Http\Middleware\VerifyCsrfTokenミドルウェアは X-CSRF-TOKEN 要求ヘッダーをチェックすることもできます。 たとえば、トークンを HTML の meta タグに格納できます。

<meta name="csrf-token" content="{{ csrf_token() }}">

その後、すべての要求ヘッダーにトークンを自動的に追加するように、jQuery などのライブラリに指示できます。

$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta').attr('content') }});

X-XSRF-TOKEN

Laravel は、現在の CSRF トークンを、フレームワークが生成する各レスポンスに含まれる暗号化 XSRF-TOKEN Cookie に保存します。 この Cookie の値を使用して、X-XSRF-TOKEN リクエスト ヘッダーを設定できます。

Angular や Axios など、一部の JavaScript フレームワークおよびライブラリは、同一生成元リクエストの X-XSRF-TOKEN ヘッダーにその値を自動的に配置するので、この Cookie は主に開発者の便宜として送信されます。

コメントする