IPAは「安全なSQLの呼び出し方」(PDF)を以下のURLから公開しています。
http://www.ipa.go.jp/security/vuln/websecurity.html
「安全なSQLの呼び出し方」は危険である、とするエントリを書こうかと思い、内容を確認するとそうでもありませんでした。
訂正:ツイッターで徳丸氏に確認したところ、徳丸氏もエスケープを含めたSQLインジェクション対策が必要であると考えられていた、ことを確認しました。徳丸氏にはセキュリティ専門家として大変不名誉な記述であった事を訂正し、深くお詫びいたします。内容についての修正は、識別子エスケープについてブログに書くとの事でしたのでブログの内容を確認してから修正します。
別冊の「安全なSQLの呼び出し方」は基本中の基本である「正確なテキストの組み立て」によるセキュリティ対策も解説しており、概ね安全な解説書になっています。
現在のIPAの文書はエスケープによるSQLインジェクション対策がメインと言って良いような内容になっており、全ての開発者にお薦めできる内容になっています。”日本語版(2010年3月18日公開)”となっているので随分前に改定されていたようです。
元々SQLはテキストベースのインターフェースを持つシステムです。SQLはインターフェースというより4GL(第四世代言語)です。言語であるためテキストを利用してどのようにデータを取得するのか、その方法を記述しデータを取得します。
テキストインターフェースを持つシステムを安全に利用する基本中の基本は、誤作動を起こさせない「正確なテキスト」を出力する事です。(参考:Webアプリセキュリティの基本ルール)
テキストインターフェースを持つシステムでも、エスケープ処理を省略できるAPIが用意されている場合があります。実務ではこれらのAPIの利用を推奨して構わないです。APIを利用した方が効率よく実行できる場合も多いです。その良い例がプリペアードクエリです。
しかし、プリペアードクエリも常に効率が良いとは限りません。(参考:SQLのエスケープ)プリペアードクエリは完全にテキストの組み立てによるクエリ作成を排除する仕組みでもありません。(参考:SQL識別子のエスケープ)
一時期「SQLインジェクション対策にはプリペアードクエリ(プレイスホルダ)さえ使えば良い」と誤った認識が広がった為、マイクロソフトなどはエスケープAPIを削除するという間違いまで犯してしまう状況になりました。
マイクロソフトは「テキスト文の組み立てによるSQLクエリの作成」を「プリペアードクエリに置き換えさせたい」という意図でエスケープAPIを作らなかったのだと思われます。しかし、私がソースコード検査をさせて頂いた.NETアプリケーションではレガシーなシステムで作成されたSQL文が多数利用されていました。これらのアプリケーションは独自にエスケープAPIを作成しエスケープ処理をするという、セキュリティ対策としては本末転倒のような状況になっていました。
現在のIPAの文書は文字リテラルのエスケープを解説していますが、識別子とSQL語句についてはまだ解説されていません。これらの解説を追加すれば”本当に”「安全なSQLの呼び出し方」になると思います。
多少追記が必要ですが、エスケープを詳しく解説しているので文脈からWebアプリセキュリティの基本ルールである「正確なテキスト管理」が必要であることは理解できると思います。古いIPAのSQLインジェクションの解説文書は「危険である」と考えていましたが、今は足りない部分がありますが一応「安全である」と思います。
関係者の皆様、別冊の公開ありがとうございました。次回の改定では是非、基本中の基本である正確なテキスト作成、識別子のエスケープ、SQL語句のバリデーションにも言及して頂けると有難いです。
データベースの開発に関わっている方にはリテラルのエスケープAPIは勿論、識別子のエスケープAPIもネイティブクライアントライブラリに用意して頂きたいです。PostgreSQLは随分前からAPIを提供しています。
追記:エスケープを無くせばOK、と勘違いして失敗した事例 XPath 1.0を書きました。根本的なセキュリティ対策とは?こちらもどうぞ!IPAのセキュリティ対策に何が足りないのか、分かり易く解説したエントリはオレオレSQLセキュリティ教育は論理的に破綻しているです。
「安全なSQLの呼び出し方」は識別子エスケープを全く解説していません。識別子エスケープが無いので、まだ危険とも言えます。
もっと根本的な話ではインジェクション対策の基礎の基礎が欠けていると言うことです。
参考
- Webアプリセキュリティの基本ルール
- エスケープファースト、この順序はかわらない
- 根本的なセキュリティ対策とは?
- 出力先のシステムが同じでも、出力先が異なる、を意識する
- APIとエスケープ/バリデーションとセキュリティ
- エンジニア必須の概念 – 契約による設計と信頼境界線