PostgreSQLがSQLインジェクションの脆弱性を修正

PostgreSQLプロジェクトは、PostgreSQL 8.1、8.0、7.4、7.3の最新バージョンを本日リリースした。この最新バージョンでは、SQLインジェクション(SQL injection)の脆弱性が修正されている。

この脆弱性は、今年3月に石田朗雄、大垣靖男、石井達夫の3名によって発見された。石田と大垣は日本PostgreSQLユーザグループの会員であり、石井はSRA-OSS日本支社に勤務している。この3名は、情報処理推進機構(IPA)セキュリティセンタのためにPostgreSQLほかのオープンソースソフトウェアを調査していた。

彼らは、PostgreSQLはSQLインジェクションに対して脆弱であり、PostgreSQLを実行している何らかのアプリケーションを通じてSQLインジェクション攻撃を受ける可能性があることを発見した。PostgreSQLのコア開発者であるJosh Berkusによれば、この脆弱性は2006年4月1日に石井からPostgreSQLコアチームに報告された。同チームはこの脆弱性が深刻な問題であることを確認し、パッチの作成に取りかかった。

脆弱性の概要

この脆弱性は、Shift_JIS(SJIS)、8-bit Unicode Transformation Format(UTF-8)、16-bit Unicode Transformation Format(UTF-16)、BIG5などのマルチバイトエンコーディングを使用しているPostgreSQLサーバが、信頼されていない入力(たとえばWebフォームからの入力など)を受け付ける場合に問題となる。

Berkusによれば、「データベースに書き込む文字列を、regexや、PHP3のaddslashes()やmagic_quotesなどの場当たり的な方法でエスケープしている」アプリケーションは特に危険だということだ。「これらの方法は、文字列を安全に処理するためのデータベース固有のコードを迂回することになるので、安全性のためには、このようなアプリケーションを書き直す必要があるだろう」。さらに彼は、PHP 4.0ではセキュリティリスクのためにaddslashes関数が非推奨とされたにもかかわらず、いまだに「頭が痛くなるほど」多くのPHPアプリケーションがこの関数を使っている、と指摘している。

addslashesの問題点

addslashesの問題点は、PostgreSQLの今回の脆弱性が発見されるずっと前から指摘されている。Chris Shiflettは、addslashesが無効なマルチバイト文字を単一引用符に変換してSQLインジェクション攻撃を可能にするしくみを次のように説明している。

仮に私がSQLインジェクション攻撃を計画したとしよう。その場合、単一引用符をバックスラッシュでエスケープするというのは最も基本的でつまらない方法である。しかし、もしもあなたのサイトでaddslashes()を使っていればしめたものだ。私が0xbf27のようなコードを挿入しさえすれば、addslashes()がこれを0xbf5c27という「有効なマルチバイト文字+単一引用符」の形に書き換えてくれる。つまり、エスケープ処理が行われているにもかかわらず、単一引用符を挿入できるというわけだ。これは、0xbf5cというコードが2つの文字ではなく1文字と見なされることによる。バックスラッシュがどこかに消えてしまうのだ。

PostgreSQLに加えられた変更

最新バージョンのPostgreSQLでは、無効なマルチバイト文字を除外するとともに、client_encodingに脆弱なエンコーディング形式が指定されている場合には、文字列リテラル内の単一引用符をエスケープするバックスラッシュを除外するようになっている。

また、必要に応じてバックスラッシュの使用を許可するためのbackslash_quoteパラメータが導入されている。ただしこのパラメータは、危険な状態に置かれることを承知した上で使用する必要がある。

最新バージョンのPostgreSQLでは、UTF-8に関する脆弱性は解消されているはずだが、Berkusによれば、SJIS、BIG5、GBKなどの極東圏用エンコーディングに関しては安全とは言い切れない。これらのエンコーディングでバックスラッシュ方式のエスケープを使い続ける場合は、「パラメータ化されたプリペアドクエリのみを使用するアプリケーションにしない限り」安全とは言えない。

さらにPostgreSQLプロジェクトは、データベースをSQLインジェクション攻撃から守るために次のような追加手順を推奨している。

  1. しっかりしたデータベースセキュリティ設計を採用し、publicデータベースロールに割り当てるアクセス権は厳しく制限する
  2. クエリを実行する際にはパラメータ化されたプリペアドステートメントを使用する(例:”SELECT * FROM table WHERE id = ?”)
    (v5.0より前のPHPはこの機能を適切にサポートしていないので注意)
  3. Webアプリケーションからクエリを実行する際には、データベースにクエリを直接送信するのではなく、ストアドプロシージャを使用する
  4. 重要なデータはハッシュまたは暗号化した形式でデータベースに格納する

脆弱性の影響を受けるバージョン

本日リリースされたものより前のバージョンのPostgreSQLはすべて、この脆弱性を含んでいる。この脆弱性はPostgreSQLのドライバにも影響を与える。Berkusによれば、今週末までにはODBC、Ruby、Perl、.Net、C++用の新しいドライバが提供される予定である。

現時点では、PostgreSQL 8.1.4、8.0.8、7.4.13、7.3.15のソースパッケージが公開されている。Berkusによれば、「大部分のプラットフォーム」用のバイナリパッケージも、48時間以内にPostgreSQLプロジェクトまたはベンダのアップデートを通じて入手可能になる見込みである。PostgreSQL 7.2以前のバージョンを使用しているユーザは、PostgreSQL 7.2のメンテナンスは2004年に終了しているので、新しいリリースのPostgreSQLにアップグレードするべきである。

アップグレードの前には、FAQリリースノートを一読しておくことをお勧めする。

NewsForge.com 原文