yamory Blog

油断できないSQLインジェクション。その種類とWebアプリにおける対策

SQLインジェクション(SQL Injection、略称: SQLi) は、バックエンドにおけるデータベース操作に悪意のあるSQLクエリを注入して、意図していないデータにアクセスできる脆弱性および攻撃手法です。データベースには、企業の機密情報や顧客の個人情報などが保存されているため、攻撃者はこの機密情報を狙って取得を試みようとします。

SQLインジェクションは、攻撃が成功すると、Webアプリケーション内に留まらず、ビジネスまで広範囲に悪影響を与えます。ユーザーリストを不正に表示できたり、データベースのテーブル全体の削除できたり、場合によっては攻撃者がデータベースの管理者権限を取得できたりする可能性もあります。

SQLインジェクションによって顧客の個人情報(電話番号、住所、パスワード、クレジットカード情報など)が流出した場合、顧客の信頼も失ってしまいます。

本記事では、SQLインジェクションの概要・脆弱性の種類についてご紹介し、Web開発者としてできる対策方法について解説していきます。

start yamory

どのくらい発生しているのか

SQLインジェクションはどのくらい発生しているのでしょうか。
以前クロスサイトスクリプティング(XSS)とは?でもご紹介したように、情報処理推進機構(IPA)が四半期ごとにとりまとめている「ソフトウェア等の脆弱性関連情報に関する届出状況」から2019 年第 4 四半期(10 月~12 月)の資料を見ていきましょう。

vulnerability status report
ウェブサイトの脆弱性の種類別の届出状況(IPAの資料より引用)

「SQLインジェクション」は、クロスサイトスクリプティング、DNS情報の設定不備に続き多く発生しており、過去2年間の届け出内訳を見ても件数は少ないものの、恒常的に発生していることが伺えます。
SQLインジェクションは対策が進んでいるとはいえ、いまだに発生する脆弱性といえるでしょう。

どうしてSQLインジェクションは発生するのか

SQLインジェクションについてご紹介する前に、まずはSQL(Structured Query Language)について簡単にご紹介しましょう。

SQLクエリについて

SQLは、データベースから必要なデータを読み書きするための標準化された言語です。クエリと呼ばれる命令文(コマンド)を通して、レコードの取得、更新、削除ができます。

SQLインジェクションの例

例として、あるユーザーの情報を取得するために、http://www.example.com/?userid=20というURLにアクセスすると、データベースに対して以下のクエリが発行されるとしましょう。

SELECT * FROM user WHERE user_id = 20;

SQLインジェクションを実行しようとする攻撃者は、以下のようなURLに変更してアクセスすることで、クエリが変化することを期待して意図しないデータを取り出そうと試みます。

http://www.example.com/?userid=20+or+1=1;--

このURLにアクセスすると、SQLクエリに利用する値として 20 or 1=1 をWebアプリケーション側で受け取ることになります。アプリケーション側で実装されたコードが、入力する値に対してバリデーション(検証)処理と後述するプレースホルダーの利用がされていない場合、以下のようなクエリが生成されます。

SELECT * FROM user WHERE user_id = 20 or 1=1; --;

上記のようなクエリが生成されると 1=1 というステートメントは常に true となってしまい、データベース内のすべてのユーザー情報を返してしまうことになるのです。
そのため、正しい意図したクエリになるように修正が必要です。

SQLインジェクションの種類・攻撃手法

SQLインジェクション脆弱性の種類および攻撃手法として、いくつかの種類があります。
代表的なものとして「インバンドSQLインジェクション」「ブラインドSQLインジェクション」について紹介します。

インバンドSQLインジェクション(In-Band SQLi, Classic SQLi)

インバンドSQLインジェクションは、SQLインジェクション攻撃の中で最も一般的で簡単できるものです。いずれもWebアプリケーションからのレスポンスを収集して分析していくことになります。

エラーベースSQLインジェクション(Error-Based SQLi)
攻撃者がデータベースに対してエラーメッセージを生成させるアクションを実行します。攻撃者は、これらのエラーメッセージを見てデータベース構造を調査できることになり、別の攻撃方法を考えるきっかけを与えることになります。

UNIONインジェクション(Union-Based SQLi)
UNIONインジェクションは、複数のSELECTステートメントの結果を1つの結果に結合し、HTTPレスポンスの一部に結果が含まれて返ってくるインバンドSQLインジェクションです。テーブルを結合させることができるため、アプリケーションのテーブルだけでなくシステムが元々持っているテーブルを読み出すことも可能になります。

ブラインドSQLインジェクション(Inferential SQLi, Blind SQLi)

ブラインドSQLインジェクションは、攻撃者がデータをサーバーに送信し、サーバーのレスポンスと動作を観察・分析することにより、攻撃先の理解を深める攻撃方法です。

サーバーからのレスポンスから直接データを盗み出すものではなく、不正なSQLとページのレスポンスの違いを見て、データベースの管理に関わる情報(実行しているユーザーの情報やテーブル名など)を盗み出すものになります。
データベースからの結果やデータが攻撃者に転送されることはないため、ブラインドSQLインジェクションと呼ばれます。

サーバーのレスポンスや挙動に依存するため、悪用するのに時間がかかる傾向にありますが、他の種類のSQLインジェクションと同じくらいリスクになりえます。

どういった対策をすれば良いのか

それでは、Webアプリケーションの開発者にとって、どのような対策を行えば良いでしょうか。

WebアプリケーションにおいてSQLインジェクションが発生するのは、SQLのクエリ(構文)が意図しないクエリになってしまうことが原因です。
構文の意味が変わらないように修正を行うことがまず第1の対策といえるでしょう。

SQLクエリをプリペアドステートメント/プレースホルダで組み立てる

昨今のWebアプリケーション開発においては、DBアクセスライブラリやO/Rマッパーを利用してクエリを発行することが一般的になってきていると思います。

DBアクセスライブラリやO/Rマッパーには、プリペアドステートメント/プレースホルダと呼ばれるクエリの一部と変数をバインドさせる機構が備わっており、意図したクエリになるように処理を行ってくれます。

実際、多くのO/Rマッパーでは、先述したプレースホルダーなどの安全なSQL発行を行う構文と、それを基本的に利用するようにドキュメントが整備されている傾向にあります。
そのため、開発者によって安全ではない書き方をしてしまうといったミスを防げる利点があります。是非活用するようにしましょう。

すでにプリペアドステートメント/プレースホルダを活用されている方は、使っていないところがないかどうか、今一度確認されることをお勧めします。

ユーザーがリクエストした値を検証し、エスケープ処理を行う

ユーザーから受け取った文字列をバリデーション(検証)し、意図したSQLクエリになるようにエスケープ処理を行うようにしましょう。

例えば一覧ページの絞り込みフィルターのようにURLのクエリパラメーターと連動するような箇所、ログインフォームなどユーザーの個人情報を格納したテーブルにアクセスするような箇所は注意が必要です。

PHP + MySQL構成の一例にはなりますが mysqli_real_escape_stringPDO::quote 関数を用いることでエスケープ処理が可能です。

DBアクセスライブラリ、O/Rマッパーの導入を検討する

エスケープ処理を行う方法もありますが、安全なSQLを発行するという観点で前項でご紹介した「プリペアドステートメント/プレースホルダで組み立てる」アプローチも検討してください。

データベースのエラーメッセージをレスポンスボディに含めない

APIからデータベースにクエリを投げてエラーとなった場合、SQLのエラーがAPIのレスポンスボディまで返すような実装になっている場合、攻撃者はここからSQLエラーメッセージの特徴を見てデータベースの種類やバージョン、利用している文字セット等を推察できてしまいます。今一度、エラーハンドリング機構に問題がないか、確認しましょう。

ライブラリやツールを最新版にアップデートする

データベースアクセスライブラリやO/Rマッパーライブラリ、またデータベースにアクセスできる管理ツールにおいても、SQLインジェクションの脆弱性が発見されるケースがあります。
つい先日も、MySQL管理ツール「phpMyAdmin」において、SQLインジェクションの脆弱性が発見され、修正されたバージョンが提供されています。
(詳しくはNVDによるCVE-2020-5504, JVNによる JVNDB-2020-01438をご参照ください)

ライブラリやツールに脆弱性が発見されたら対応できるようにウォッチすることが重要です。定期的に最新版にアップデートするようにしましょう。

脆弱性診断/DASTを検討する

Webセキュリティの観点では「Webセキュリティはどこから手をつければよいのか?」でもご紹介したように、脆弱性診断サービスを利用することも検討してください。
また、Webアプリケーションファイアウォール(WAF)を導入することでSQLインジェクションを引き起こすような、怪しいクエリやリクエストを検知・ブロックすることで、SQLインジェクションの発生を軽減することも可能です。

最後に

SQLインジェクションはクロスサイトスクリプティング同様、Web開発者も運営者も注意を払うべき脆弱性であり、また適切な対策を行えば防ぐことができる脆弱性です。

ユーザーが入力できる値をチェックし、正しいクエリが作られることを意識することが、SQLインジェクション対策における意識付けであり、解消へ向けての第一歩となります。
Webに携わる開発者・管理者として、セキュア開発を意識しながら開発を進めていくことが大切です。

また、稼働中のWebサイト・Webアプリケーションに対して、SQLインジェクションの検証・対策を実施するのは大変な労力がかかります。脆弱性が見つかっても開発やビジネスの優先度から対策が後回しになったり、放置になるケースもあるのではないでしょうか。

SQLインジェクションは攻撃が成功した場合、個人情報の流出に直結しやすく、ご利用のユーザーや顧客に被害の影響が大きいため、継続的にリソースを確保して検証および対策を実施していきましょう。

最後になりますが、Webアプリケーションで用いられるフレームワーク・ライブラリに潜むSQLインジェクションの脆弱性については、yamoryを用いることで検出が可能です。ぜひ一度お試しいただければ幸いです。

オープンソース脆弱性管理ツール yamory

  • 利用中のOSSを抽出し
    脆弱性を自動スキャン
  • 脆弱性への対応優先度を自動で分類
  • 組織規模に合わせたプランを選択可能

フリー

¥0

個人向け

1件ずつ Immediate な脆弱性を管理

1チームまでの開発チーム作成

yamory を使いはじめる

プロ

有料料金はお問い合わせください

中〜大規模組織向け

無制限で Immediate な脆弱性を管理

無制限の開発チーム作成

開発チームを俯瞰できるセキュリティチーム機能

危険な脆弱性の Slack 連携通知機能

特定のソフトウェアの脆弱性一覧を表示

特定の脆弱性を含むソフトウェア一覧を表示

30日間の無料トライアルを開始