トランソニックソフトウェア

ブログ
BLOG

2023.10.05

【Laravel道場】LaravelでもSQLインジェクション!?

LaravelでもSQLインジェクション!?

Laravelは、PHPで不動の人気を誇るフレームワークです。Web開発に必要な機能がたっぷり盛り込まれ、手軽にリッチなアプリケーションを開発することができます。

もちろん、セキュリティもばっちりで、基本的な脆弱性はLaravelが事前に対策してくれています。

LaravelのSQLインジェクション対策

Laravelでデータベースの操作を行う際には、Eloquentやクエリビルダを使います。例えば、usersテーブルからデータを取得するには、以下のようなコードを書きます。

// Eloquent
$user = User::where('username', '=', 'transonic')->first();

// クエリビルダ
$user = DB::table('users')->where('username', '=', 'transonic')->first();

MySQLのログを確認したところ、以下のようなクエリが発行されていました。
23 Prepare select * from `users` where `email` = ? limit 1
23 Execute select * from `users` where `email` = 'transonic' limit 1
23 Close stmt
23 Prepare select * from `users` where `email` = ? limit 1
23 Execute select * from `users` where `email` = 'transonic' limit 1
23 Close stmt

どちらも同じクエリになっていますが、注目すべきは 「?」です。これは、プレースホルダーと呼ばれるもので、SQLインジェクションの対策として使用されています。

開発者が特に意識しなくても、セキュリティ対策をしてくれているので、うっかり脆弱性を作りこんでしまう心配がありません。

危険なパターン

いくら対策されているとはいえ、何をやってもいいわけではありません。場合によっては、LaravelでもSQLインジェクションが発生してしまいます。

1. Rawメソッド

例えば、以下のようにRawがつくメソッドを使うと、SQLインジェクションにつながる可能性があります。

$search = $request->get('search');
$user = DB::table('users')->whereRaw("email = '{$search}'")->where('deleted_at', '=', null)->get();

ここで、$user_inputに「’ OR 1=1 — – 」と入力されると、検索条件に関わらずusersテーブルの全行が取得されてしまいます。

64 Prepare select * from `users` where email = '' OR 1=1 -- -' and `deleted_at` is null
64 Execute select * from `users` where email = '' OR 1=1 -- -' and `deleted_at` is null
64 Close stmt

Rawメソッドは他にもいくつかあります。

  • raw
  • selectRaw
  • whereRaw/orWhereRaw
  • havingRaw/orHavingRaw
  • orderByRaw
  • groupByRaw

など…

詳しくはドキュメントを参考にしてください。

2. DB::statementメソッド

statementメソッドはSQLクエリを直接発行できる機能で、こちらもRawメソッドと同様な危険性をはらんでいます。

$search = $request->get('search');
$user = DB::statement("SELECT * FROM mt_users WHERE email = '{$search}'");

Rawの場合と同じように任意のSQLクエリが実行できます。

109 Prepare SELECT * FROM users WHERE email = '' OR 1=1 -- -'
109 Execute SELECT * FROM users WHERE email = '' OR 1=1 -- -'
109 Close stmt

SQLインジェクションの影響

SQLインジェクションの脆弱性がある場合、どのような影響が発生するでしょうか?

アプリケーションの構成にもよりますが、以下のような攻撃につながるリスクがあります。

  • 機微な情報の流出
  • 認証のバイパス
  • 任意コードの実行
  • システムのダウン

など…

アプリケーションがクラッシュするだけならいいですが、ユーザーの個人情報が流出したり、サーバーの乗っ取りにつながる可能性もあるので注意しなければいけません。

対策

Laravelでは、基本的なSQLインジェクション対策がなされているので、Eloquentやクエリビルダを適切に使っている限りは特に対策は必要ありません。

ただし、Rawメソッドやstatementメソッドは不必要に使わないことをおすすめします。どうしても使用しなければならない場合は、必ずプレースホルダーを使ってバインディングしてください。

DB::table('users')->whereRaw("email = ?", [$select])->first();

以下のように、シングルクォーテーションがエスケープされています。

116 Prepare select * from `mt_users` where email = ? limit 1
116 Execute select * from `mt_users` where email = '\' OR 1=1 -- -' limit 1

まとめ

Laravelには、便利な機能がたくさん用意されているので、あまり深く考えずどんどん使ってしまいますが、中身を理解していないと思わぬ落とし穴にハマってしまいます。セキュリティ対策の基本をしっかり押さえて、安全なアプリケーションを構築しましょう!

以上。