OWASP Top 10 を通じて、Webアプリケーションのセキュリティを学び直しています。
今回は、Injection(インジェクション)についてまとめます。
Injectionとは、注入という意味。Webアプリのセキュリティでは、「悪意あるコード」の注入を意味します。

Laravelアプリケーション開発時の対策や、バイブコーディング(生成AIコーディング)でも役立つ対策も考えていきますね。
*本記事では、執筆時点で最新版のOWASP Top 10: 2021の内容をもとにしています。
Injection(インジェクション)
Injection(インジェクション)について、公式説明ページはこちら:
テスト対象アプリケーションの94%でインジェクションのテストが行われ、そのうち平均3%のアプリケーションでインジェクション脆弱性が確認されました。
全体としてはInjectionカテゴリで合計274,000件の脆弱性が検出されています。
また、インジェクションはアプリケーション内の複数箇所で発生することも多く、1箇所で脆弱性が見つかった場合、他の入力処理部分にも同様の問題が潜んでいる可能性があります。

ゴキブリを1匹見つけたら100匹いると言いますが、これとちょっと似ているかも。微妙なたとえですが…。
CWE(共通脆弱性タイプ)
このカテゴリーに含まれる主なCWE(脆弱性分類)は次のとおりです。
※XSSは、以前のOWASP Top 10(2017年版)では独立したカテゴリでしたが、2021年版ではInjectionの一種として統合されています。
-
CWE-79:クロスサイト・スクリプティング(XSS)
-
ユーザー入力をそのままWebページに出力することで、悪意あるスクリプトがブラウザ上で実行されてしまう脆弱性
-
-
CWE-89:SQLインジェクション
- ユーザー入力を直接SQL文に組み込むことで、データベースを不正に操作されてしまう脆弱性
-
CWE-73:ファイル名やパス名の外部制御
- ユーザーが指定したファイル名やパスを検証せずに使用することで、意図しないファイルへのアクセスを許してしまう脆弱性
対策
このリスクに対して、下記のような対策が挙げられます。
- 安全なAPIや、パラメータ化されたクエリを実行するORMを使用
- SQL文を文字列として組み立てるのではなく、変数を安全にバインドできる仕組みを使い、ユーザー入力が「命令」として実行されないようにします。
- サーバーサイドでバリデーション実施
- ユーザーが入力したデータを検証する仕組みをサーバーサイドにいれます。ただし、特殊文字の入力を許可するケースもあるので、これだけでは完全な防御にはなりません。
- 特殊文字のエスケープ処理
- コードとして実行されないように、特殊文字をエスケープ処理します。
- ユーザー入力をそのままクエリ構文やコマンド、ファイルパスなどに使用するのは危険です。
*分かりやすく書きなおしていますが、正確な元文章を確認したい場合は、こちらご覧ください。
Laravelでの対策
「そういわれても、具体的に何をしたら」という方のために、Laravelでの関連する対策・技術をまとめます。Laravelには、しっかり防御してくれる機能が備わっています。
Eloquent ORM / クエリビルダーを使う
Laravelでは、データベースの値を処理する際にEloquent ORMまたはクエリビルダを使います。
Eloquentやクエリビルダでは内部的にプリペアドステートメントを使い、入力値を自動的にエスケープしてくれます。
Eloquent ORM利用例
Eloquent ORMを使って、$emailと一致するユーザーを取り出すコードは、次のように書きます。
【Eloquent ORM】
|
1 |
$user = User::where('email', $email)->first(); |
クエリビルダ利用例
同じ内容をクエリビルダで書くと、次のようになります。
【クエリビルダ】
|
1 |
$user = DB::table('users')->where('email', $email)->first(); |
生のSQL文(危険な例)
なお、次のようにselect文を直接書くこともできますが、これは推奨されません。
【生のSQL文】
|
1 |
$user = DB::select("SELECT * FROM users WHERE email = '$email'"); |
ユーザーが $email に文字列を入れられた場合、悪意ある入力によってデータベースの全件取得やテーブル削除などの深刻な被害が発生する可能性があります。
たとえば、$emailに次のような値が指定されたとします。
|
1 |
$email = "hituji@example.com; DELETE FROM users;"; |
すると、次のようなSQLが組み立てられ、SELECT に続けて DELETE が実行されてしまう危険性があります。
|
1 |
SELECT * FROM users WHERE email = 'hituji@example.com'; DELETE FROM users; |
select文を直接書くのは避け、Laravelが提供しているEloquent ORMまたはクエリビルダを使うようにしましょう。
Laravelのクエリビルダについて詳細はこちら。
LaravelのEloquentについて詳細はこちら。
XSS対策にはBladeのエスケープ機能を使う
Laravelでは、ビューファイルで二重波カッコ {{ }} を使うと、自動的にエスケープ処理されます。
【エスケープ処理】
|
1 |
{{ $user->name }} |

これまたLaravelユーザーにはお馴染みの書き方ですね。
もし $user->name に「<script>alert(‘ハッキング!’)</script>」のような悪意あるコードが入っていても、<>の部分が自動で変換され、次のようなただの文字列になります。
|
1 |
<script>alert('ハッキング!')</script> |
安心な機能ですが、もしHTMLタグなどを画面に表示したい場合には、困ってしまいますよね。
そういった場合は、{!! !!} を使うと、HTMLコードをそのまま実行できます。
【エスケープ処理】
|
1 |
<span class="token">{</span><span class="token">!</span><span class="token">!</span> $user->name <span class="token">!</span><span class="token">!</span><span class="token">}</span> |

便利ですが、表示するデータによっては危険な処理です。
{!! !!} を使う場合は、信頼できる管理者が入力したデータなど、完全に安全が確認できる場合に限りましょう。
エスケープ処理について書かれている公式マニュアルページはこちら。
バリデーションルールを適用する
ユーザーが入力した内容をデータベースに保存する前に、サーバー側でバリデーションチェックを行いましょう。

基本中の基本ですが、非常に大事です。
【バリデーション例】
|
1 2 3 4 |
$validated = $request->validate([ 'email' => 'required|email|max:255', 'age' => 'required|integer|min:0|max:150', ]); |
バリデーションについて書かれている公式マニュアルページはこちら。
バイブコーディングでも役立つ全般的な注意点
バイブコーディング(生成AIコーディング)では、AIがセキュリティ対策を含むコードを自動生成してくれることもあります。
ただし、その内容は必ずしも完全ではありません。生成されたコードを確認する必要はあります。
また、どういった値を入力可能とするかは、設計段階で考えておく必要があります。これに応じて、バリデーションルールを考えます。
そして、セキュリティ対策には「穴」があります。たとえば先ほどのLaravelの例ですと、エスケープ処理を行わずに、データベースのデータを出力したりできます。こういった例外処理を行う場合には、はたして本当に安全かどうか、検討が大事です。
さいごに
インジェクションは防ぎやすい反面、根絶が難しいともされています。
というのも、フォーム送信を通じていれられる以外にも、検索を通じてであったり、様々な形で攻撃される可能性があるためです。
ユーザーが入力した値をそのままデータベースに保存したり、コマンドを実行したりするコードは、非常に危険です。
こうした危険からWebアプリを守るには、便利な機能やツールをできる限り使いつつ、開発者自身もしっかりセキュリティを意識していくことが大切です。

いつもながら、やっぱり「人」の判断は重要です。技術面だけでなく、設計にも力をいれていきたいですね。
なお、今回ご紹介したXSS(クロスサイトスクリプティング)対策や、データベースの処理や、バリデーションのかけかたについては、拙著『Laravelの教科書』でも解説しています。
クリックするとamazonページへ。
↓↓↓

-120x68.png)
