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

2009年2月20日(金)
近藤 伸明

前提条件的な対策(設計時の対策)

 SQLインジェクションには、前提条件的な対策として、「開発用のエラーメッセージをブラウザに出さない」「データベースの権限を正しく設定する」「入力パラメタのチェック」「日本語の誤認識を防ぐ」といった、設計時に当然行うべき対策がある。以下にそれらの項目について説明する。

 1つ目が開発用のエラーメッセージをブラウザに出さないという対策だ。開発時のデバッグではエラーメッセージは有益だが、本番稼働時にも同じ状態のままで放置すると、攻撃者にとってSQLインジェクションの攻撃状況を確認するのに有益な情報源を与えてしまう。

 アプリケーションで作成したエラーメッセージを表示するのはよいが、エラーメッセージに必要以上の情報を表示したり、状態に応じてエラーメッセージの種類や表示内容を変えたりしてはいけない。攻撃者はそれらの情報を観察し、ブラインドSQLインジェクションを仕掛ける可能性があるからだ。ブラウザ上には、処理が失敗したことが分かる程度の簡単なエラーメッセージを表示し、詳しくはログファイルなどに出力し、ユーザーに見せないようにすべきである。これらのエラー時の処理は設計時から適切に盛り込むべきものだ。

 2つ目がデータベースの権限を正しく設定するというものだ。許可されたユーザーのみがデータベースへのアクセスできることはもちろん、設計時にWebサーバーからデータベースサーバーにアクセスする際も同様にユーザーの権限を厳密に設定するべきである。

 まれに、Webサーバーのアクセス権限がデータベースの管理者権限のまま運用されている場合がある。この場合、アプリケーション側の不備によってSQLインジェクションが成功すると、データベースのすべての操作が可能となり、データベースが乗っ取られてしまうからだ。

 よって、Webサーバーがデータベースにアクセスするスキーマ、機能の範囲ごとに、データベースの権限を割り当てたユーザーを作成し、そのユーザーを使用してアクセスすべきである。つまり、データベースを検索するだけならば、検索する対象のスキーマを参照するだけの権限、データベースを検索/更新するだけならば対象のスキーマを検索/更新するだけの権限のユーザーを作成して、Webサーバーからそのユーザーを使用してデータベースにアクセスすべきである。

 3つ目が入力パラメタのチェックである。入力項目ごとにアプリケーションで決められたチェック処理を行うようにする。例えば郵便番号の場合は、「123-4567」の形式のみを有効とする、あるいは都道府県を「01~48」のコードで表している場合は、「01~48」の文字列のみを有効とするなどである。

 これらの対策だけでは、SQLインジェクションの脆弱性の本対策にはならないが、このような対策を実装することで2重、3重の防壁を設けることとなる。

 4つ目が文字コードの誤認識を防ぐということだ。前述したようにエスケープ処理の前提として、日本語などのマルチバイトに対する処理がきちんと行われている必要がある。

 例えば、MySQLとPostgreSQLは「\」をエスケープする必要がある。「\」を16進数のASCIIコードで表した際の「0x5c」は、Shift_JISの漢字には2バイト目にも含まれる場合がある。この場合、マルチバイト非対応の処理系で処理した場合、「0x5c」を「\」と勘違いし、「\\」へエスケープしてしまう。この場合、想定しているよりも「\」が1つ多く生成されてしまい、本来エスケープされるべき文字へのエスケープ処理が無効化されてしまう。結果、SQLインジェクションが成立してしまうのである。例を図2-1に示す。

 このような現象はShift_JISにのみ起きる訳ではなく、すべての文字コードにおいて発生しうる。これに対する適切な対策は、図2-2の通りである。なおもちろん、文字コードのチェックはSQLインジェクションに限った話ではなく、Webアプリケーション開発で一般的に行う必要がある。

ユーザー企業と開発企業の責任と意識

 さて、技術的な対策だけでは、SQLインジェクションの被害はなくならない。ユーザー企業(発注企業)も、開発だけではなく運用までを含めた全体的な問題として認識しなければならない。

 受託開発における瑕疵(かし)担保期間は通常1年程度(契約内容によって異なる)なので、期間終了後は開発会社の責任を追及できない。実際に事件/事故が発生した場合に謝罪するのはユーザー企業である。

 また、契約締結時には、対象システムにおけるセキュリティー要件を明確化し、開発業者と責任の分担を行うべきである。

 これには、セキュリティー要件を策定するためのコストが初期費用として追加される。しかし、開発当初にセキュリティー要件を明記し、それに沿って開発を進めるほうが、事後に対策をとるよりも運用を含めた全体でのセキュリティー対策費用を大幅に削減することができるのである。

 なぜなら、実装完了後に診断した結果、膨大な量の脆弱性が報告される可能性があるからだ。これを修正するためには、実装の見直しと、既に通過したテスト工程をやり直す必要がある。

 一方、開発途中で都度レビューや脆弱性診断を行えば、開発者は正しい実装を学習することができ、徐々に問題のあるプログラムが生み出される確率を減らすことができる。結果、実装完了後の脆弱性診断の結果は良好なものとなり、手戻りによる工数増大や納期遅延を回避することができる。これは、ユーザー企業にとっても開発業者にとっても必ずよい結果を生むはずである。

 また、セキュリティー要件を追加することで、開発業者からは追加の費用を求められるかもしれない。しかし、そこはパートナーとして開発業者とよく話し合いをしてほしい。単なる外注先としてではなく、これからWebアプリケーションを一緒に育てていくパートナーとして、セキュリティーに対する共通認識をもって進めていく必要がある。そのためには、ユーザー企業でもある程度のコストを負担しつつ、開発会社もセキュリティー要件を自社内の品質向上のために必要なものとして取り込み、社内教育や技術の向上の一環としてユーザー企業に協力するなどお互いの歩み寄りが必要となるが、それがお互いによい結果を生むことになる。

 もう1つのポイントとして、納品の受け入れ時に事前に策定したセキュリティー要件が満たされていることをチェックすることが重要である。

 これがなされないと、セキュリティー要件を契約時に盛り込む意味が全くない。毎回実施するのが望ましいが、既に十分な信頼関係がある場合には抜き打ち的に実施するだけでも効果は上がる。チェックは、セキュリティー診断を実施する会社に依頼してもよいし、市販の診断ツールを使ってもよい。

 一方、開発企業(受注業者)が行うべき対策については、図2-3にまとめた通りである。

 続いて運用時の対策を紹介する。

株式会社神戸デジタル・ラボ

2003年神戸デジタル・ラボに入社。
2007年からWebセキュリティ診断業務を事業化し、現在に至る。
2008年4月に経済産業省から発表された「モデル取引・契約書(追補版)」のセキュリティガイドライン ワーキング・グループ委員として「Web アプリケーションセキュリティ」を担当。
2010年10月、CSS2010にてセキュリティ関連論文を発表するなど、診断業務のかたわらセキュリティ基盤研究開発業務に活躍中。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています