EnterpriseZine(エンタープライズジン)

EnterpriseZine(エンタープライズジン)

テーマ別に探す

データベース・セキュリティの実装 第4回 最前線の防御を可能にするOracle Database Firewall

edited by DB Online   2011/11/16 00:00

最終回は、今年に新たにデータベース・セキュリティ製品に加わったOracle Database Firewallについて取り上げよう。Firewallという名がつくことから、何となく機能のイメージはできるかもしれないが、このOracle Database Firewallは、今までのデータベース関連の製品とは毛色の違う、非常に面白い製品である。しかしながら、その中身は質実剛健のごとく的を射たものであり、その代表的な機能について触れていきたい。

SQLインジェクション

 その前に、やはりSQLインジェクションについて説明が必要かもしれない。SQLインジェクション攻撃は以前から存在してはいたが、特に2005年頃から猛威を振いはじめ、2010年もその衰えは見せてはいない。Gumblar(ガンブラー)と並ぶウェブサイトを経由した攻撃の2大トレンドといってもよいだろう。「SQLインジェクション」と検索すれば、もっと詳細な情報のサイトにたどり着くことはできると思うが、念のためこのSQLインジェクションの仕組みを簡単に説明すると、

SQLインジェクション
SQLインジェクション

 商品検索のWEBサイトがあったとしよう。アプリケーションは、製品を検索する画面なので当然、商品名や商品コードなどの文字が入ってくるものだという前提で作成されている。そこで、上記のようなSQLを入れてみて検索したらどうだろう。すると、本来実行されるべきSQLを強制的に書き換え、顧客情報を検索するSQLを注入(インジェクト)されてしまった。これが、SQLインジェクションである。通常のWEBサイトへのHTTPアクセスからSQLを操作し、任意のSQLを実行し、データの搾取や改ざんを行うことができてしまうのだ。実際にサイト改ざんやクレジットカード情報を含む個人情報を抜き取られてしまった事件が多く発生している。

 このSQLインジェクション攻撃が成功するには、以下の二つの条件を満たす必要がある。

  •   WEBサイトにアプリケーションの脆弱性がある
  •  データベースに格納したデータを用いてWEBページを動的に生成するWEBサイトである

 上記の例の場合、アプリケーションには致命的な脆弱性がある。SQLの組み立て方に問題があるのだ。最も基本的な例を見てみよう。

 SELECT 列1, 列2, 列3 FROM 製品情報 WHERE NAME = ' + 検索フォーム文字 + "'"

 というように単純にユーザーの入力した値を文字列連結してSQLを組み立てている。

 ユーザーは必ずしも期待した文字列を入力してくれるわけでないので、この検索フォーム文字に' UNION SELECT列1, 列2, 列3 FROM 顧客情報 - と入力されたとすると、

 SELECT列1, 列2, 列3 FROM 製品情報 WHERE NAME = '' UNION SELECT列1, 列2, 列3 from 顧客情報 -- '

 製品情報表を検索しているSELECT分に、顧客情報表を検索するSQLがUNION ALLによってくっつけられてしまい、SQLが成立し実行されてしまうのである。(※データベースの種類によって攻撃が成功するSQLは異なる)。これは、あくまでも一例であって攻撃方法は多種多様に存在する。WEBサイトにインジェクション可能な入口が見つかれば、そこから様々なSQLを注入しながらデータ・ディクショナリの情報を検索し、クレジットカード情報や個人情報などの換金性の高い情報が入っている表を探り当てられてしまうかもしれない。また、攻撃者はWEBサイトを一つ一つ攻撃をしているわけでなく、自動化されたツールを使って世界中のWEBサイトをランダムにアクセスし、攻撃可能なWEBサイトの目星をつけてからより詳細な攻撃が行われる。ツールさえ手に入れば、だれにでも実現できてしまうことが被害の増加を招いていると言えよう。

 このようなSQLインジェクションの対策は、アプリケーションの脆弱性をなくすことである。

 SQLにとって特別な意味を持つ記号(メタ文字)が含まれていないかをチェックすること、これは、ユーザーが入力した値を判別して排除するようにするエスケープ処理が当てはまる。(※Oracle Databaseには入力値を検証するDBMS_ASSERTパッケージが用意されている)。しかし、メタ文字はデータベースによって異なる場合があり、チェックが漏れる可能性は否定できない。

 抜本的な対策としては、静的プレースホルダ(prepared Statement)を使用することである。バインド変数を使うといったほうが分かりやすいかもしれない。

 例えば、SELECT * FROM PRODUCTS WHERE NAME = ' + バインド値 + "'"

 バインド変数とは、上記のようなSQLを予めデータベース側に用意をしておき、SQLの実行する段階でバインド値を送信することである。

 仮に、上記のSQLインジェクションを目的とした不正なSQLをバインド値に入れたとしても、SQLの文法上正しくないので、攻撃として成立しない。バインド変数はSQLの解析が最小化されることからSQLの再利用性が高くなりパフォーマンス向上のメリットが大きくなることが良く知られているが、セキュリティの面からも大きな恩恵を受けることができる。IPAに「安全なSQLの呼び出し方」として公開されている資料があるので、是非参照して欲しい。


著者プロフィール

  • oracletech.jp編集部(オラクルテックジェイピーヘンシュウブ)

    oracletech.jpは、オラクル・データベースと関連製品をお使いいただいている皆様、開発に携わっているエンジニアの皆様、オラクル製品を販売いただいている皆様すべてにとって有益な情報源となることを目指しています。 エンタープライズ系ITを中心に、製品情報や技術情報からテクノロジー・トレンド、キャンペーンやイベント/セミナー情報まで多岐にわたります。日本オラクルの社員だけでなく、外部の有識者やフリーランス・ライターを含む幅広い執筆陣により"ベンダー発"の枠を脱したコンテンツ発信を目指します。 好奇心が、エンジニア人生を豊かにする。 oracletech.jp

バックナンバー

連載:oracletechアーカイブス!
All contents copyright © 2007-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5