結論
適当なミドルウェアを作成してhandleを以下のようにした後、webのミドルウェアグループに追加する。
$response = $next($request);
//$response->header('X-Frame-Options', 'deny');ではだめ(後述)
$response->headers->set('X-Frame-Options', 'deny'); //状況に応じてsameoriginやallow-fromを指定
return $response;
クリックジャッキングとは
攻撃者が作成したページの上に透過iframeなどでターゲットのwebサイトを埋め込み、ユーザーに対してターゲットのwebサイト上で何かしらのアクションをさせる攻撃のこと。下の図で言えばユーザーからはピンクのページしか見えておらず、指示通りに「ココをクリック」の場所を押したつもりが、実際にはサイトAで情報公開を選択してしまったことになる。
画像:IPA 「知らぬ間にプライバシー情報の非公開設定を公開設定に変更されてしまうなどの『クリックジャッキング』に関するレポート」(https://www.ipa.go.jp/files/000026479.pdf) より
Laravelではこれを防ぐような仕組みが組み込まれていないので、自分でなんとかしましょうという記事です。
クリックジャッキングを防ぐには
上の説明から分かるように、自分のwebサイトがiframeやembedなどで埋め込まれるとまずいわけです。よってこれを回避しましょうという話なのですが、最近のブラウザではレスポンスヘッダに「X-Frame-Options」を指定することで埋め込みを許可する、しないを制御することができます。
参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
レスポンスヘッダにこのオプションを指定するため、LaravelではMiddlewareを利用するのが良さそうです。
$ php artisan make:middleware AddXFrameOptions
<?php
namespace App\Http\Middleware;
use Closure;
class AddXFrameOptions
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'deny'); //状況に応じてsameoriginやallow-fromを指定
return $response;
}
}
APIは関係ないのでwebグループの方に先ほどのミドルウェアを追加します。
protected $middlewareGroups = [
'web' => [
...
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\AddXFrameOptions::class // 追加
],
...
];
curlなどでレスポンスヘッダにX-Frame-Optionsが追加されていることを確認しましょう。
$ curl -D - http://localhost/myapp
おまけ
冒頭にあるように、ミドルウェアでヘッダーを追加する際、
$response->header('X-Frame-Options', 'deny');
としてしまうと、ダウンロード等でファイルを返す際に以下のようなエラーが出ます。
Call to undefined method Symfony\Component\HttpFoundation\BinaryFileResponse::header()
https://stackoverflow.com/questions/29289177/binaryfileresponse-in-laravel-undefined にあるように、header()はSymfonyのResponseには定義されていないからだそうです。ややこしや。