Skip to main content

Laravelでオープンリダイレクトの脆弱性を防ぐ方法

著者
Headshot of Kevin Kimani

Kevin Kimani

feature laravel open redirect

2023年12月27日

0 分で読めます

オープンリダイレクトの脆弱性は、適切な検証やサニタイズを行わずに、ユーザーが入力した値によってリダイレクト先が決まる場合に発生します。この脆弱性を悪用する攻撃者は、一見信頼できそうなリンクをユーザーに送り、クリックすると悪意のあるWebサイトへリダイレクトさせることができます。その結果、フィッシング攻撃などの悪意ある行為につながる可能性があります。Laravelでは、開発者がリダイレクト先を検証したり、許可リストに登録したりしていない場合によく発生します。

この記事では、オープンリダイレクトの脆弱性と、Laravelでの防止方法について解説します。また、Snykを使ってコードや依存関係に潜むこの脆弱性を検出する方法も紹介します。

Laravelにおけるオープンリダイレクトの脆弱性とは

オープンリダイレクトの脆弱性は、Webアプリケーションが外部ユーザーにリダイレクト先のURLを指定させる場合に発生します。多くの場合、リンクやボタンのクリックなど、ユーザーが操作した後にリダイレクトが行われます。ユーザーが指定するURLは、一般にアプリケーションのURLのクエリパラメーターとして含まれます。

たとえば、次のような脆弱なURLを考えてみましょう: http://example.com/redirect?url=http://malicious-site.com

適切な検証とサニタイズが行われていないと、Laravelのredirectメソッドによって、ユーザーが意図せず指定された悪意のあるサイトに誘導される可能性があります。

脆弱なアプリケーションを作成する

オープンリダイレクトの脆弱性の仕組みを理解するため、簡単な脆弱なアプリケーションを作成しましょう。後ほど、この脆弱性を防ぐ方法を実装します。

手順を進めるには、次のものが必要です:

  • ローカルマシンにPHPとComposerがインストールされていること。

  • ローカルマシンにphp-xmlおよびphp-curl拡張機能がインストールされていること。

  • ローカルマシンにNode.jsとnpmがインストールされていること。

  • Webブラウザーとコードエディター。本ガイドではVisual Studio (VS) Codeを使用します。

このチュートリアルのコードはすべてこちらのGitHubリポジトリで公開しています。

準備ができたら、アプリケーションの作成を始めましょう。

ローカルマシンで適切なディレクトリに移動し、ターミナルでそのフォルダーを開きます。次のコマンドを実行して、Composer経由でLaravelインストーラーをグローバルにインストールし、新しいLaravelプロジェクトを作成します:

composer global require laravel/installer

laravel new open-redirect-vulnerability-demo

このコマンドが機能しない場合は、composer create-project laravel/laravel open-redirect-vulnerability-demoを実行して新しいプロジェクトを作成してください。

ターミナルに表示されるプロンプトでは、次の選択肢を選びます:

  • スターターキットをインストールしますか?: スターターキットなし

  • 使用するテストフレームワークはどれですか?: PHPUnit

  • Gitリポジトリを初期化しますか?: いいえ

  • アプリケーションで使用するデータベースはどれですか?: SQLite

アプリケーションを作成したら、コードエディターでopen-redirect-vulnerability-demoディレクトリを開きます。オープンリダイレクトの脆弱性があるルートを作成するには、routes/web.phpファイルを開き、/ルートを次のコードに置き換えます:

Route::get('/vulnerable', function (Request $request) {
   // Get the 'redirect' parameter from the query string
   $redirectUrl = $request->input('redirect');

   // Perform the redirect
   return redirect($redirectUrl);
});

web.phpファイルの先頭に、次のuse文があることを確認してください:

use Illuminate\Http\Request;

オープンリダイレクトの脆弱性の仕組みを確認するには、php artisan serveコマンドでサーバーを起動し、Webブラウザーを開きます。この例では、攻撃者がユーザーをリダイレクトさせようとする悪意のあるURLとしてhttps://www.google.com/を使用します。

ブラウザーでhttp://127.0.0.1:8000/vulnerable?redirect=https://www.google.com/にアクセスすると、https://www.google.com/にリダイレクトされます。

作成した/vulnerableルートは、入力の検証とサニタイズが不十分なため、オープンリダイレクトの脆弱性があります。具体的には、URLからredirectパラメーターを取得し、そのURLが安全か、アプリケーションのドメイン内にあるかを確認せずに、指定されたWebページへリダイレクトします。コードはredirectパラメーターで指定されたURLへ無条件にリダイレクトするため、URLを細工してユーザーをフィッシングサイトに誘導したり、マルウェアをダウンロードさせたり、その他の危険な行為に誘い込んだりできます。

この場合、攻撃者は本物のサイト(http://127.0.0.1:8000)を複製し、ページが読み込まれたときに、実際には偽サイトであるにもかかわらず、ユーザーに正規のサイトだと思わせることができます。ユーザーがその悪意あるサイトにログインすると、気付かないうちに認証情報を攻撃者に渡してしまいます。

Laravelでオープンリダイレクトの脆弱性を防ぐ方法

オープンリダイレクトの脆弱性はよくある攻撃手法ですが、防ぐことができます。次に挙げるベストプラクティスを参考にしてください:

固定のリダイレクト先を使用する

リダイレクト先を固定すると、ユーザーはアプリケーション内の信頼できる事前定義済みの場所にしかリダイレクトされません。この方法はオープンリダイレクトの脆弱性のリスクを効果的に軽減できるため、堅牢な防御策として実装することをおすすめします。

現在のコードに固定のリダイレクト先を実装するには、/vulnerableルートを次のコードに置き換えます:

Route::get('/', function () {
   return view('welcome');
})->name('home');

Route::get('/vulnerable', function (Request $request) {
   return redirect()->route('home');
});

このコードでは、リダイレクト先をLaravelアプリケーション内の特定の信頼できるルート(つまり内部ルート)に限定しています。これにより、攻撃者が外部のURLへ誘導する悪意あるURLを作成できなくなります。先ほど使用した悪意のあるURLhttp://127.0.0.1:8000/vulnerable?redirect=https://www.google.com/にアクセスして、この修正をテストできます。

リダイレクト先の許可リストを作成する

オープンリダイレクトの脆弱性を防ぐもう1つの方法は、信頼できるリダイレクト先のリストを定義することです。この対策により、承認済みのURLにのみリダイレクトされるようにできます。

このLaravelプロジェクトにこの方法を実装するには、/vulnerableルートを次のコードに置き換えます:

Route::get('/vulnerable', function (Request $request) {
   // Define trusted redirect destinations
   $whitelistedDestinations = [
   	'https://snyk.io/',
   ];

   // Get the 'redirect' parameter from the params
   $redirectUrl = $request->input('redirect');

   // Check if the input URL is in the whitelist
   if (in_array($redirectUrl, $whitelistedDestinations)) {
   	// Perform the redirect
   	return redirect($redirectUrl);
   }

   // Handle invalid redirects, for example:
   return redirect('/'); // Redirect to a safe default page
});

このコードでは、https://snyk.io/を信頼できるリダイレクト先としています。URLのredirectパラメーターの値を$whitelistedDestinations配列と照合します。信頼できるリダイレクト先のいずれかと一致すれば、リダイレクトが実行されます。一致しない場合は、安全なデフォルトページにリダイレクトされます。

この方法をテストするには、ブラウザーでhttp://127.0.0.1:8000/vulnerable?redirect=https://www.google.comにアクセスします。https://www.google.comは$whitelistedDestinations配列に含まれていないため、Laravelアプリケーションのホームページに自動的にリダイレクトされます。一方、http://127.0.0.1:8000/vulnerable?redirect=https://snyk.io/にアクセスすると、$whitelistedDestinations配列に含まれているため、https://snyk.io/にリダイレクトされます。

別のドメインへのリダイレクトを禁止する

アプリケーションが別のドメインへリダイレクトしないようにすることで、ユーザーをアプリケーションのドメイン内に誘導できます。また、信頼できる環境外へのリダイレクトが発生する場合に、ユーザーへ適切に知らせ、慎重に操作できるようにします。この方法は、全体的なセキュリティとユーザーの信頼性を高めます。

このLaravelプロジェクトにこの方法を実装するには、/vulnerableルートを次のコードに置き換えます:

Route::get('/vulnerable', function (Request $request) {
   $inputUrl = $request->input('redirect');

   // Prepend the protocol if missing
   if (!parse_url($inputUrl, PHP_URL_SCHEME)) {
   	$inputUrl = 'http://' . $inputUrl;
   }

   $parsedInputUrl = parse_url($inputUrl);

   // Check if the URL is valid and has a host component
   if ($parsedInputUrl && array_key_exists('host', $parsedInputUrl) && $parsedInputUrl['host'] === 'localhost') {
   	return redirect()->to($inputUrl);
   }

   // Disallow redirect with a 403 Forbidden status code
   return response('Forbidden: Cannot redirect to another domain', Response::HTTP_FORBIDDEN);
});

また、web.phpファイルの先頭に次のuse文を追加してください:

use Illuminate\Http\Response;

このコードは、URL形式のユーザー入力を受け取るルートを定義します。プロトコルが指定されていない場合はhttp://を先頭に追加し、URLのホストがlocalhostかどうかを確認します。一致すればリダイレクトを許可します。一致しなければ403 Forbiddenレスポンスを返し、別のドメインへのリダイレクトを禁止するとともに、異なるドメインへのリダイレクトは禁止されていることを示すメッセージを表示します。

Snyk IDE拡張機能でオープンリダイレクトの脆弱性を検出する

オープンリダイレクトの脆弱性を手軽に検出したい場合は、Snyk IDEセキュリティ拡張機能(Snyk Visual Studio Code拡張機能など)の利用をご検討ください。このツールは、コード内のオープンリダイレクトの脆弱性を検出し、脆弱性の詳細(セキュリティレベルを含む)や防止のためのベストプラクティス、修正に使えるコードスニペットの例を提示します。

Snyk Visual Studio Code拡張機能は簡単に使い始められます。まず、拡張機能をインストールし、設定して、認証を行います。

拡張機能の動作を確認するには、先ほどと同じ脆弱なコードを使用します。routes/web.phpファイルを開き、/vulnerableルートを次のコードに置き換えます:

Route::get('/vulnerable', function (Request $request) {
   // Get the 'redirect' parameter from the query string
   $redirectUrl = $request->input('redirect');

   // Perform the redirect
   return redirect($redirectUrl);
});

ファイルを保存し、VS CodeのサイドバーからSnykを選択します。スキャンがまだ実行されていない場合は、「コードセキュリティ」の下にある再スキャンボタンをクリックします:

Visual Studio Codeに、redirectクエリパラメーターを読み取ってリダイレクトレスポンスを返すLaravelのweb.phpルートと、Snykのスキャンパネルが表示されています。

スキャンが完了すると、脆弱性の一覧が表示されます。結果からweb.phpを展開し、オープンリダイレクトを選択します。Snyk拡張機能に脆弱性の詳細と修正方法が表示されます:

Visual Studio CodeでSnyk CodeがLaravelのweb.phpルートにあるオープンリダイレクトの脆弱性を検出し、修正案を提示しています。

Snyk拡張機能はコード内の脆弱な箇所もハイライト表示します。その箇所にカーソルを合わせると、脆弱性の詳細を確認できます:

Laravelのリダイレクト呼び出しを表示するコードエディター。オープンリダイレクトの脆弱性(CWE-601)に関する警告と、その防止方法が示されています。

この拡張機能では、アプリケーションのオープンソースライブラリに含まれる脆弱性を検出して修正できるオープンソースセキュリティも利用できます。オープンリダイレクトの脆弱性を含め、オープンソースライブラリに脆弱性が見つかった場合は、Snyk拡張機能のウィンドウに結果が表示されます:

Visual Studio Codeに、リクエストパラメーターで指定されたURLにユーザーをリダイレクトするLaravelのルートが表示され、Snykのセキュリティパネルも見えています。

まとめ

この記事では、Laravelアプリケーションにおけるオープンリダイレクトの脆弱性と、フィッシング攻撃やマルウェアの配布など、そこに伴う潜在的なリスクについて解説しました。また、固定のリダイレクト先の実装、許可するリダイレクト先のホワイトリスト登録、外部ドメインへのリダイレクト禁止などの対策も紹介しました。これらの方法により、ユーザーが信頼できる事前定義済みの場所にのみリダイレクトされるようになり、Laravelアプリケーションのセキュリティを大幅に強化できます。

セキュリティをさらに強化したい場合は、Snyk IDE拡張機能の利用をご検討ください。Snykを活用すれば、オープンリダイレクトをはじめ、あらゆる種類の脆弱性からLaravelアプリケーションをより強固に保護できます。

Snyk Visual Studio Code拡張機能はコードベースをスキャンして脆弱性を特定し、実践的な分析情報を提供します。これにより、開発者は潜在的な脅威が本番環境に到達する前に発見できます。Snykの包括的なセキュリティソリューションを活用することで、開発者はLaravelアプリケーションを先回りして保護し、プロジェクト全体のセキュリティ態勢を強化できます。

Capture the Flagを始めよう

オンデマンドのバーチャル入門ワークショップで、Capture the Flagの課題の解き方を学びましょう。


続きを読む

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSecのご紹介:AI開発のスピードに対応するセキュリティ

AI駆動型開発のスピードに、従来のセキュリティワークフローは追いついていません。SnykのAgentic AppSecは、セキュリティエージェントが脆弱性を継続的に検出、修正、検証し、人が基準を定められるようにします。

blog feature ai violet
Blog

VulnBump:AIエージェントはビルドを壊さずに脆弱な依存関係を修正できるか?

VulnBumpは、実際の依存関係アップグレード307件を対象にAIエージェントをテストします。脆弱性が解消され、ビルドとテストが成功した場合にのみ、修正としてカウントされます。

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。