概要
データベースと連携したウェブアプリケーションの多くは、利用者からの入力情報を基にSQL文(データベースへの命令文)を組み立てています。ここで、SQL文の組み立て方法に問題がある場合、攻撃によってデータベースの不正利用をまねく可能性があります。このような問題を「SQLインジェクションの脆弱性」と呼び、問題を悪用した攻撃を、「SQLインジェクション攻撃」と呼びます。
発生しうる脅威
SQLインジェクション攻撃により、発生しうる脅威は次のとおりです。
- データベースに蓄積された非公開情報の閲覧
個人情報の漏えい 等
- データベースに蓄積された情報の改ざん、消去
ウェブページの改ざん、パスワード変更、システム停止 等
- 認証回避による不正ログイン(*1)
ログインした利用者に許可されている全ての操作を不正に行われる
- ストアドプロシージャ等を利用したOSコマンドの実行
システムの乗っ取り、他への攻撃の踏み台としての悪用 等
注意が必要なウェブサイトの特徴
運営主体やウェブサイトの性質を問わず、データベース(*2)を利用するウェブアプリケーションを設置しているウェブサイトに存在しうる問題です。個人情報等の重要情報をデータベースに格納しているウェブサイトは、特に注意が必要です。
届出状況(*3)
SQLインジェクションの脆弱性に関する届出件数は他の脆弱性に比べて多く、届出受付開始から2014年第4四半期までに、ウェブサイトの届出件数の 11% に相当する届出を受けています。また、ソフトウェア製品の届出も、ウェブサイトの届出件数ほど多くはありませんが、少なからずあります。下記は、IPAが届出を受け、同脆弱性の対策が施されたソフトウェア製品の例です。
- 「DBD::PgPP」における SQL インジェクションの脆弱性
https://jvndb.jvn.jp/jvndb/JVNDB-2014-000142 - 「Piwigo」における SQL インジェクションの脆弱性
https://jvndb.jvn.jp/jvndb/JVNDB-2014-000094 - 「サイボウズ ガルーン」における SQL インジェクションの脆弱性
https://jvndb.jvn.jp/jvndb/JVNDB-2014-000024
根本的解決
1-(i)-a
SQL文の組み立ては全てプレースホルダで実装する。
SQLには通常、プレースホルダを用いてSQL文を組み立てる仕組みがあります。SQL文の雛形の中に変数の場所を示す記号(プレースホルダ)を置いて、後に、そこに実際の値を機械的な処理で割り当てるものです。ウェブアプリケーションで直接、文字列連結処理によってSQL文を組み立てる方法に比べて、プレースホルダでは、機械的な処理でSQL文が組み立てられるので、SQLインジェクションの脆弱性を解消できます。
プレースホルダに実際の値を割り当てる処理をバインドと呼びます。バインドの方式には、プレースホルダのままSQL文をコンパイルしておき、データベースエンジン側で値を割り当てる方式(静的プレースホルダ)と、アプリケーション側のデータベース接続ライブラリ内で値をエスケープ処理してプレースホルダにはめ込む方式(動的プレースホルダ)があります。静的プレースホルダは、SQLのISO/JIS規格では、準備された文(Prepared Statement)と呼ばれます。
どちらを用いてもSQLインジェクション脆弱性を解消できますが、原理的にSQLインジェクション脆弱性の可能性がなくなるという点で、静的プレースホルダの方が優ります。詳しくは本書別冊の「安全なSQLの呼び出し方」のプレースホルダの項(3.2節)を参照してください。
1-(i)-b
SQL文の組み立てを文字列連結により行う場合は、エスケープ処理等を行うデータベースエンジンのAPIを用いて、SQL文のリテラルを正しく構成する。
SQL文の組み立てを文字列連結により行う場合は、SQL文中で可変となる値をリテラル(定数)の形で埋め込みます。値を文字列型として埋め込む場合は、値をシングルクォートで囲んで記述しますが、その際に文字列リテラル内で特別な意味を持つ記号文字をエスケープ処理します(たとえば、「'」→「''」、「\」→「\\」等)。値を数値型として埋め込む場合は、数値リテラルであることを確実にする処理(数値型へのキャスト等)を行います。
こうした処理で具体的に何をすべきかは、データベースエンジンの種類や設定によって異なるため、それにあわせた実装が必要です。データベースエンジンによっては、リテラルを文字列として生成する専用のAPI(*4)を提供しているものがありますので、それを利用することをお勧めします。詳しくは、「安全なSQLの呼び出し方」の4.1節を参照してください。
なお、この処理は、外部からの入力の影響を受ける値のみに限定して行うのではなく、SQL文を構成する全てのリテラル生成に対して行うべきです。
1-(ii)
ウェブアプリケーションに渡されるパラメータにSQL文を直接指定しない。
これは、いわば「論外」の実装ですが、hiddenパラメータ等にSQL文をそのまま指定するという事例の届出がありましたので、避けるべき実装として紹介します。ウェブアプリケーションに渡されるパラメータにSQL文を直接指定する実装は、そのパラメータ値の改変により、データベースの不正利用につながる可能性があります。
保険的対策
1-(iii)
エラーメッセージをそのままブラウザに表示しない。
エラーメッセージの内容に、データベースの種類やエラーの原因、実行エラーを起こしたSQL文等の情報が含まれる場合、これらはSQLインジェクション攻撃につながる有用な情報となりえます。また、エラーメッセージは、攻撃の手がかりを与えるだけでなく、実際に攻撃された結果を表示する情報源として悪用される場合があります。データベースに関連するエラーメッセージは、利用者のブラウザ上に表示させないことをお勧めします。
1-(iv)
データベースアカウントに適切な権限を与える。
ウェブアプリケーションがデータベースに接続する際に使用するアカウントの権限が必要以上に高い場合、攻撃による被害が深刻化する恐れがあります。ウェブアプリケーションからデータベースに渡す命令文を洗い出し、その命令文の実行に必要な最小限の権限をデータベースアカウントに与えてください。
以上の対策により、SQLインジェクション攻撃に対する安全性の向上が期待できます。データベースと連携したウェブアプリケーションの構築や、SQLインジェクションの脆弱性に関する情報については、次の資料も参考にしてください。
脚注
(*1) 後述 「1.4 セッション管理の不備」で解説する「発生しうる脅威」と同じ内容です。
(*2) 3.2の修正例1~3を参照。 https://www.ipa.go.jp/files/000017316.pdf
(*3) 最新情報は、下記URLを参照してください。
脆弱性関連情報に関する届出状況: https://www.ipa.go.jp/security/vuln/report/press.html
(*4) 実行環境によっては、エスケープ処理を適切に行わない脆弱性が指摘されているAPIもあります。
その場合は修正パッチを適用するか、別の方法を検討して下さい。
CWE
- CWE-89: SQLインジェクション
https://jvndb.jvn.jp/ja/cwe/CWE-89.html - CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (2.8)
https://cwe.mitre.org/data/definitions/89.html
参考URL
- IPA: 安全なSQLの呼び出し方
https://www.ipa.go.jp/security/vuln/websecurity.html#sql - IPA: 知っていますか?脆弱性 (ぜいじゃくせい) 「1. SQLインジェクション」
https://www.ipa.go.jp/security/vuln/vuln_contents/sql.html - IPA: 「2014年度情報セキュリティ事象被害状況調査」報告書について
https://www.ipa.go.jp/security/fy26/reports/isec-survey/index.html