SQLインジェクションとは何か
ここでSQLインジェクションについて簡単におさらいしましょう。以下のSQL呼び出しを例として考えます。
SELECT * FROM books WHERE author='$author'
$authorの箇所には外部から指定された著者名が埋め込まれるとします。ここで、$authorとしてO'Reillyという文字列が指定されたらどうなるでしょうか。実際に埋め込まれたSQL文は以下に示すとおりです。
SELECT * FROM books WHERE author='O'Reilly'
文字列O'Reillyに含まれるアポストロフィ(シングルクォート)により、author=の後の文字列が終端し、あとに続くReilly' が文字列の外にはみ出しています。上記はSQL文として正しくないためにエラーになります。しかし、そのあとに続くReillyの箇所に、SQL文としてエラーにならないようにつじつまを合わせると、攻撃者が元のSQL文の意味を変えることができます。これがSQLインジェクション攻撃であり、このような攻撃を許す状態をSQLインジェクション脆弱性と呼びます。
SQLインジェクション対策もれで損害賠償の判決も
SQLインジェクション脆弱性に関して、2014年1月23日に東京地裁で興味深い判決が出ました。ECサイトがSQLインジェクション攻撃を受けてクレジットカード情報が漏洩した事件について、サイト運営者がアプリケーションの開発会社に対して損害賠償を請求して、結果として約2262万円の損害賠償が命じられたというものです。この判決は確定しています。
判決文を読みますと、サイト発注者はセキュリティ対策について特に仕様として指示はしていなかったもようですが、開発会社側の「専門家としての責務」として、特に要求されていなくてもSQLインジェクション対策をしているべきところ、それを怠っていた過失が認定されています。
従来は、発注者の多くはこの判決のようにセキュリティ対策については開発会社にお任せということが多く、一方開発会社は、セキュリティの対策をすると開発費用が高騰し、それを見積もりに転嫁できないため、脆弱性対処に消極的になってしまうという状況がありました。
これについて、私としては脆弱性対処は発注者と開発会社の双方に責任があると考えていますが、前述のような判決が出た以上は、開発会社は「セキュリティについて求められてなくても」SQLインジェクション対策くらいは自衛のためにしておくべきでしょう。
OWASPのドキュメントに見るSQLインジェクション対策
OWASPはSQLインジェクションをまとめたドキュメントとしてSQL Injection Prevention Cheat Sheetを公開しています。このドキュメントには、SQLインジェクション対策として以下が推奨されています。
- Defense Option 1: Prepared Statements (with Parameterized Queries)
- Defense Option 2: Stored Procedures
- Defense Option 3: Escaping All User Supplied Input
日本語に訳すと以下のようになります。
- 選択肢1: プリペアードステートメント(およびパラメータ化クエリ)
- 選択肢2: ストアドプロシージャ
- 選択肢3: すべてのユーザからの入力をエスケープ
このうち、選択肢1のプリペアードステートメントと選択肢3のエスケープについては日本語のドキュメントでもよく見かけるもので、独立行政法人情報処理推進機構(IPA)が発行する「安全なSQLの呼び出し方」などの解説でもこれらは言及されています。
一方、選択肢2のストアドプロシージャがSQLインジェクション対策として有効という解説は、日本語の資料ではあまり見かけません。そこで本稿では、プリベアードステートメントやエスケープによる対策はこれらのドキュメントに譲り、なぜSQLインジェクション対策としてストアドプロシージャが有効かという理由を解説し、加えてストアドプロシージャを使う上での注意点を説明しましょう。