Laravelのセキュリティについてグダグダ書いていくべ!
今僕は業務でサーバ処理をLaravelで書いているのですが、一般ユーザも使うECサイトを構築中なので、セキュリティにはそれなりにシビアです。
ということで今回は、Laravelのセキュリティについて解説していきます!
※本記事は少しずつ更新していきます。ご了承ください。
僕のプロフィールはこちら
Laravelのセキュリティについて
Laravelで開発をする際、よくあるのはAPIを作成するケースだと思います。
画面は最近流行りのVue.jsなどを使い、AWSのAPI Gatewayを通してLaravelのAPIを実行するみたいな感じですね。
つまりは、Laravelのセキュリティと言っても、Laravelで何をどこまでやるかで話は変わってくるわけです。
今回はあくまで、Laravelでできるセキュリティ対策をメインに話をしていくので、システム構成がどうだとかは考えず、ざっくり書いていこうと思います。
LaravelのHTTPヘッダのデフォルト
Laravelにアクセスすると、どのようなHTTPヘッダが返ってくるのかを理解しないと、セキュリティ対策のしようがありません。
Laravelプロジェクトを新規作成し、「http://localhost:8000/」にアクセスすると以下のようなヘッダが返却されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
General Request URL: http://localhost:8000/ Request Method: GET Status Code: 200 OK Remote Address: 127.0.0.1:8000 Referrer Policy: no-referrer-when-downgrade Response Headers Cache-Control: no-cache, private Connection: close Content-Type: text/html; charset=UTF-8 Date: Sun, 03 Feb 2019 08:40:14 +0000 Date: Sun, 03 Feb 2019 08:40:14 GMT Host: localhost:8000 Set-Cookie: XSRF-TOKEN=eyJpdiI6ImV0N2Rvc1JcL3hmSlBtMThIK0V6SWZBPT0iLCJ2YWx1ZSI6ImlSZks5M0tZc00wdnB5eUlwZzhtc0dQNVVwQWJJTm1xbWdCbXFaRjdkdWVOR3hXNHdvQ2FzdFdKZ0NcL0lFRUl1IiwibWFjIjoiMDhkMjFiMjJjZjExY2YxYmU5M2JkNWViMWNkNTk3ZWNkM2Q4YmQzYTdhMzVlODJiNzU3YmRkNjEwM2E5MTc5YSJ9; expires=Sun, 03-Feb-2019 10:40:14 GMT; Max-Age=7200; path=/ Set-Cookie: laravel_session=eyJpdiI6IkhXc2xmK21hT2xQd3ZIOE1FT3hlK1E9PSIsInZhbHVlIjoiZjlGVVV0MVFOc0dNREczb3d4cURTOWFKcXJzM2M3VWJVbU9ZZ2NSWG9WZkdJNHNpWmhIdWVKcldON2RuVmtiQyIsIm1hYyI6Ijg2Y2E4Y2E3NjY4MGJjY2Y3MTNmMTBmZjI1MWIwYTUyMjU5N2MwYTMxZWU4MGUwMWJhZGY2YmI2YjFmY2RjZTEifQ%3D%3D; expires=Sun, 03-Feb-2019 10:40:14 GMT; Max-Age=7200; path=/; httponly X-Powered-By: PHP/7.3.0 Request Headers Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: ja,en-US;q=0.9,en;q=0.8 Cache-Control: max-age=0 Connection: keep-alive Cookie: XSRF-TOKEN=eyJpdiI6ImxkWm8xcG4ydkdTOGVkeW1HeGJ2OVE9PSIsInZhbHVlIjoieDdiaGpFaHJ1SG5COFBCRUhpOTBzaDhQRzlVN0pscys3SEhqMkpIWWE4czFySmY4XC9mbWxtYXBNOHpJS0hVcWwiLCJtYWMiOiJjYjE3NTg1ZWM2OTY5YWUxZDk5NDVkNWJmMjA5YzkzOGIyMDYxMzZhMDVhMjkwYTg1ZDIyZGY4MjJiMWI2NTMyIn0%3D; laravel_session=eyJpdiI6InZQeFU2MzVkMEJMdG5CZTA0Y2FJZnc9PSIsInZhbHVlIjoic2gyOFRJZDJ5XC9wUUNDNklMRjZ0RTQxdFRXUlRVTUFEV2M1TnhBSWJtTSs5YWlVdWFcL0hVeGtCSDhuSVlzdTQ0IiwibWFjIjoiMzgyNzExMWZjODQ0MjEzMTdkNzY2OWMzYzRiZGM1Y2I2MDUzM2FkMWE3MjA1OGEyZGNlZThiMTAxOGI2ZWY1ZSJ9 Host: localhost:8000 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 |
Chromeブラウザ⇒F12⇒Network⇒localhost⇒Headersで見れます。
Laravel×キャッシュコントロール
キャッシュがブラウザに残ってしまうと、データを意図せぬ形で抜き取られる可能性があります。
キャッシュが残るのを防ぐために、レスポンスヘッダにキャッシュをさせない設定を記載します。
デフォルト設定
1 |
Cache-Control: no-cache, private |
Laravelは、デフォルトでキャッシュをさせない設定になっています。
が、明示的に記載した方が良いだろうということで、レスポンス用のミドルウェアを追加します。
※ミドルウェアは、「php artisan make:middleware ResponseHeader」で追加できます。
また、追加したミドルウェアは「Kernel.php」に追記しておきましょう。
キャッシュコントロール対策
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php namespace App\Http\Middleware; use Closure; /** * レスポンスヘッダ用ミドルウェア * ※主にセキュリティ対策用 */ class ResponseHeader { /** * レスポンスヘッダを書き換える * * @param Request $request * @param Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); /** * キャッシュコントロール対策 * ※デフォルトは「no-cache, private」だが、明示的に記載 */ $response->header('Cache-Control', 'no-cache, private'); return $response; } } |
明示的に「‘Cache-Control’, ‘no-cache, private’」を記載しています。これでOK!
Laravel×クリックジャッキング
クリックジャッキングでよく取り上げられるのは「iframe」です。
iframe経由で画面を表示されることで、意図しない使われ方をされる可能性があります。
ということで、iframeをシステム内で使わない以上、iframe関連は禁止した方が無難です。
デフォルト設定
Laravelはデフォルトで何も設定されていません。
クリックジャッキング対策
「X-Frame-Options」に「Deny」を設定することで対策します。
先ほどのミドルウェアにクリックジャッキング対策を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php namespace App\Http\Middleware; use Closure; /** * レスポンスヘッダ用ミドルウェア * ※主にセキュリティ対策用 */ class ResponseHeader { /** * レスポンスヘッダを書き換える * * @param Request $request * @param Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); /** * キャッシュコントロール対策 * ※デフォルトは「no-cache, private」だが、明示的に記載 */ $response->header('Cache-Control', 'no-cache, private'); /** * クリックジャッキング対策 * ※iframeを使用させない */ $response->header('X-Frame-Options', 'DENY'); return $response; } } |
明示的に「‘X-Frame-Options’, ‘DENY’」を記載しています。これでOK!
Laravel×XSS(文字コード)
XSSにおいて、文字コードの問題は重要です。
最近のシステムはUTF-8がほとんどですが、それ以外の文字コードを意図しない形で指定されることによる脆弱性が確認されています。
デフォルト設定
1 |
Content-Type: charset=UTF-8 |
Laravelはデフォルトの文字コードが「UTF-8」となっています。
が、明示的に記載した方が良いだろうということで、ミドルウェアに追加します。
XSS(文字コード)対策
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<?php namespace App\Http\Middleware; use Closure; /** * レスポンスヘッダ用ミドルウェア * ※主にセキュリティ対策用 */ class ResponseHeader { /** * レスポンスヘッダを書き換える * * @param Request $request * @param Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); /** * キャッシュコントロール対策 * ※デフォルトは「no-cache, private」だが、明示的に記載 */ $response->header('Cache-Control', 'no-cache, private'); /** * クリックジャッキング対策 * ※iframeを使用させない */ $response->header('X-Frame-Options', 'DENY'); /** * XSS対策(文字コード脆弱性対応) * ※デフォルトは「UTF-8」だが、明示的に記載 */ $response->header('Content-Type', 'charset=UTF-8'); return $response; } } |
明示的に「‘Content-Type’, ‘charset=UTF-8’」を記載しています。これでOK!
おすすめ書籍
僕はLaravelの勉強をするのに以下の書籍を購入しました。おすすめですよ!
まとめ
セキュリティ対策は難しいっすね。。
よくシステム構成を考えずにやたらめったらセキュリティ対策をしようとする人がいるんですけど、それってなんか違いますよね。
現状のシステム構成をしっかりと理解し、どういった攻撃が防げないかを攻撃者目線で考える必要があると思うのです。
ということでまた会いましょう!