データベースへのアクセスは通常,アプリケーションを経由する。アプリケーションで作り込んだ手順を経た操作しかユーザーに許さなければ,DBセキュリティ対策の一つになる。
しかし,アプリケーションに脆弱性があると,作り込んだはずの操作手順を回避されてしまう。開発者が想定していない操作により,データベースから情報を抜き取られてしまう。
ユーザーに自由な操作を許すデータベース検索ツールも,セキュリティ面で危険な存在になり得る。
攻撃ツールが出回る
今年に入りアデコやスターツ出版が受けた不正アクセスは,Webアプリケーションの「SQLインジェクション」と呼ばれる脆弱性を悪用されたものだ。「OSやWebサーバーに最新のセキュリティ・パッチを適用する」という対策だけでは,SQLインジェクションを悪用される攻撃を防げない。
SQLインジェクションの危険性は,既に2~3年前から専門家が指摘していた。それにもかかわらず,ここにきて被害が増えた背景には,昨年秋ごろから,SQLインジェクションの脆弱性を抱えたWebサイトを調べたり,脆弱性があるWebサイトを容易に攻撃できるツールが中国系サイトを中心に公開されたことがある(画面1[拡大表示])。
これらのツールの使い方は,いたって簡単だ。攻撃対象となるWebサイトのURLを入力し,あとはGUI画面で簡単な操作をするだけでテーブル名やカラム名,テーブル内のデータを抜き出せてしまう。
このように,SQLインジェクションの脆弱性があると,アプリケーションの想定を超えた操作を許してしまう。データベース・アクセス権限の範囲内で何でもできてしまう。しかも,「SQLインジェクション対策としてデータベース側で取れる対策は,アクセス権限を必要最小限にするなど限られている」(日本オラクル 北野氏)。アプリケーションでのセキュリティ対策が不可欠である。
入力値を信じない
データベースと連携するWebアプリケーションは,Webブラウザから送信されたデータを使ってデータベースに送信するSQL文を組み立てる。ここで,Webアプリケーションの開発者が,「ユーザーは正しいデータだけを入力する」と過信し,送信されてきたデータの中身をチェックしないと,SQLインジェクションを悪用した不正アクセスを許してしまう。
以下では,データベースに登録されているユーザーIDとパスワードを基に,ユーザー認証する仕組みを考えてみよう(図10[拡大表示])。
通常,ユーザーはユーザーIDとパスワードを認証画面に入力する。例えばユーザーIDが「yoshida」でパスワードが「hoge」ならば,それらを入力して,送信ボタンをクリックする。これにより,Webアプリケーションは,「SELECT id FROM USER WHERE id ='yoshida' and password='hoge'」というSQL文を生成し,データベースに送信する。SQL文の実行結果によって,ユーザー認証できたかどうかを判定し,結果画面をWebブラウザに送信する。これが開発者がユーザーに期待する動作である。
しかし,不正ユーザー(クラッカ)は,正しいユーザーIDやパスワードではなく,意図的に特殊な文字を入力する。これにより,Webアプリケーションで組み立てるSQL文が,開発者が意図したものとは別のものに改ざんされてしまい,ユーザー認証を不正に通過されてしまう。
図10の例では,passwordとして「a' or '1'='1」という文字列を送信する。この文字列を受け取ったWebアプリケーションは,「SELECT id FROM USER WHERE id='yoshida' and password='a' or '1'='1'」というSQL文をデータベースへ送信する。問題は,このSQL文の最後にある「or '1'='1'」という条件が必ず真となり,データベースはidを返してしまうことである。判定結果として「ユーザー認証できました」と,WebアプリケーションはWebブラウザに応答してしまう。
SQLインジェクションの脆弱性があると,操作されるのがデータベースだけとは限らない。SQL文を通じて,OSのコマンドを呼び出すことも可能である。こうなると,ファイルを改ざんされたりする可能性もある。
図10の例で分かる通り,SQLインジェクションを防ぐための対策は「Webブラウザから受け取る文字をWebアプリケーションでチェックすること」である。データベースが解釈する特殊文字として,「'」や「;」などがある。これらの文字をWebブラウザから受け取ったら,それらを削除したり,別の文字に置き換えるなどのサニタイジング(無害化)が必要である。
準備済みSQL文で回避可能
サニタイジングのほかにもSQLインジェクションを防ぐ効果のある対策が,準備済みSQL文を利用することである。
準備済みSQL文とは,SQL文の一部を変数として扱い,同じようなSQL文を使い回すことでデータベースの性能劣化を防ぐための仕組みである。例えば,「SELECT * FROM TBL_A WHERE id = 1」,「SELECT * FROM TBL_A WHERE id = 2」という具合に,WHERE句の条件部分だけが異なるSQL文の場合,「SELECT * FROM TBL_A WHERE id=?」というように条件部分(この例では1や2)を変数として扱う。データベースは,「SELECT * FROM TBL_A WHERE id=」の部分だけをコンパイルし,変数部分を後から送信されてくる値に置き換えて実行する。
準備済みSQL文をJDBCのPreparedStatementで記述した例が図11[拡大表示]である。WHERE句の条件部分を変数化している。データベースはこのSQL文を解釈し,後から送信される値を変数部分と置き換えてSQL文を実行する。図11の例では,passwordカラムに「a' or '1'='1」という文字が含まれるかどうかを調べるSQL文になる。変数化しているidやpasswordの部分に特殊文字が含まれていても,SQL文は改ざんされない。
準備済みSQL文は,JDBCのPreparedStatementのほか,ASP,ASP.NET,Perl,PHPなど主要な開発言語で利用できる。
アプリを修正せずツールで対策
稼働中のWebシステムにSQLインジェクション対策を実施する場合,アプリケーションの修正が必要になる。大量のアプリケーションを抱えるWebサイトの場合,すぐには修正を加えられない可能性もある。
その場合,「Webアプリケーション・ファイアウォール」という製品の導入を検討する価値がある。これは,一般的なファイアウォールが監視するTCP/IPではなく,HTTPのパケットを監視し,不正なデータを遮断する機能を備えた製品である。
Webアプリケーション・ファイアウォールには,F5ネットワークスの「TrafficShield」,チェック・ポイント・ソフトウェア・テクノロジーズの「VPN-1 Pro」,米NetContinuumの「NC-1000」,米Terosの「FireLine」などがある。例えばTerosのFireLineで315万円から,TrafficShield 4100で920万円である。修正にかかる工数と比較して導入を検討したい。
「Accessの利用を禁止」
アプリケーションの脆弱性のほか,取材を通じて複数の企業が指摘しているのが,データベース検索ツールの危険性だ。「Accessを利用してデータベースの情報を更新したりする。しかし,Accessはデータを修正して次の行にカーソルを移すとコミットされてしまうなど非常に危険なため,利用を禁止し,専用のアプリケーションを作り,操作を制限することを検討中だ」(ウェブクルー システム部 統括ディレクター 清水誠氏)。
一番の対策はデータベース検索ツールを利用しないこと。それで業務に支障が出る場合はDB監査ログを取得するなど他の方法で監視する。アサヒインターネットサービスは,データを直接データベースから取り出す際にAccessを利用している。このため,「操作内容を監査するために,DBアカウントを個々に割り当てた上で,各ユーザーの行動をDB監査ログに保存している」(向氏)。