2014年を揺るがしたインジェクション攻撃の手口と対策:セキュリティ強化塾(2/4 ページ)
2014年はOpenSSL、Struts2、bashと、深刻な脆弱(ぜいじゃく)性が次々に公表された。特に顕著だった攻撃手口と対策を紹介する。
Webアプリケーションの脆弱性は、セキュリティ実装の不備で生まれる。自社開発アプリケーション以外に商用やオープンソース製品を用いる場合にも、同様の脆弱性が製品に含まれる場合がある。
SQLインジェクションは特に深刻な情報漏えい被害を引き起こし、OSコマンドインジェクションはインシデント報告が増えたので特に注意が必要だ。
SQLインジェクション攻撃の手口と対策
深刻な情報漏えい事件を幾つも引き起こしたSQLインジェクションの脆弱性を狙う攻撃について説明しよう。冒頭の例が示すように、データベースの奥にある機密データが、周到に構成された攻撃によって盗み出されるケースが後を絶たない。
図1で見たように、Webアプリケーションはユーザーからの入力をデータベースへの問合せ(SQL文)のパラメータとして組み入れてデータベースに送信する。入力がアプリケーションが意図していない悪意に基づく文字や構文になっていた場合、本来のデータベース処理ではなく、攻撃者が意図する処理が実行される。
本来ならアプリケーションによってエラーとして排除されるべき入力が、データベースにまで行き着いて、攻撃者が求める処理を行ってしまうわけだ。脆弱性があるアプリケーションでこの手口が使われると、データベース内の個人情報などの機密情報が閲覧される他、データの改ざんや削除、パスワードの変更、時にはシステム停止までが可能だ。
また、セッションIDの発行や管理の仕組みに不備がある場合、セッションIDの横取り(セッションハイジャック)が可能になり、正規ユーザーになりすまして許可された全ての操作を行える。ストアドプロシージャなどを利用したOSコマンドの実行により、システムの乗っ取りや他の攻撃の踏み台としての悪用も行われる可能性がある。
手口の一例
SQL文生成の一例(Perlの場合)を挙げる。次のようなSQL文で$idという変数に、ユーザーの入力を当てはめるようにした場合を考える。
$q = "SELECT * FROM atable WHERE id='$id'";
$idに入るのは文字列を想定するが、そこに次のような入力を行う。
';DELETE FROM atable--
すると生成されるSQL文は次のようになる。
SELECT * FROM atable WHERE id='';DELETE FROM atable--'
この文は、データベースの「atable」テーブルの全てのレコードを削除する。
対策
このような攻撃を防ぐには、ユーザー入力で決まるパラメータ部分を「?」などの記号(プレースホルダ)で示し、そこへ実際の値を機械的な処理で割り当てる方法(Prepared Statement)を利用するのが最も安全だ。Javaの場合は次のようになる。
PreparedStatement prep = conn.prepareStatement("SELECT * FROM employee WHERE name=?");prep.setString(1, "山田");
プレースホルダへの値の割り当てを「バインド」といい、バインドをデータベースエンジンの側で行う方式を「静的プレースホルダ」、アプリケーション側で値をエスケープ処理してバインドする方式を「動的プレースホルダ」という。
静的プレースホルダを用いると原理的にSQLインジェクションの脆弱性がなくなるので、こちらがお薦めだ。ただし、データベースによっては静的プレースホルダが利用できない場合があるのが問題だ。動的プレースホルダは、バインド処理を実現するライブラリの実装に問題があると脆弱性が生じることがある。
また、バインド機構そのものが利用できない場合には、文字列連結によるSQL文組み立てが必要になるが、特殊文字のエスケープ処理(「'」→「''」「\」→「\\」など)が必要で、データベースの種類や設定によってエスケープすべき文字が違うことから漏れや間違いが生じる危険がある。
文字入力ではなく数値入力をパラメータとする場合でも、PerlやPHPなど変数に型のない言語を使用する場合には、数値以外の文字が入力された場合に文字列として扱うので、同様の注意が必要だ。
どのような対応をすればよいかはデータベースによって異なるので、IPAの「安全なウェブサイトの作り方」の別冊の形で発行される「安全なSQLの呼び出し方」などを参考にして、適切な実装を図りたい。
「ブラインドSQLインジェクション」や情報収集のための攻撃への対策
なお、一度の攻撃で成果を得ようとするばかりでなく、たくさんの文字列を使った入力を機械的に行って、その応答を調べてテーブル名などを推測し、手間をかけても目的の情報を得る「ブラインドSQLインジェクション」という手口も使われる。
SQLインジェクション攻撃で意図した情報(検索結果)が表示されない場合に、何度もSQLインジェクション攻撃を仕掛けて少しずつ情報を得る方法だ。この手口も脆弱性を排除しておけば防止できる。
また、単にデータベースの脆弱性を探るために行われる場合もある。その際、攻撃には成功しなくても、攻撃者に返るエラーメッセージからデータベースの種類やエラー原因、エラーとされたSQL文に関する情報を拾い、次の攻撃を組み立てるための情報源とする。
データベースに関連するエラーメッセージを相手に表示しないようにする保険的対策も求められる。加えて、データベースにアクセスできるアカウントは、権限を最小限に限定することも保険的対策として有効だ。万一、1つのアカウントが奪われても広範囲のデータ閲覧や削除などの不正が行いにくくなる。
ソフトウェア製品のSQLインジェクション脆弱性
これまでにセキュリティ管理製品や複数のCMS製品にSQLインジェクションの脆弱性が発見されている。開発やサポートが終了した製品の場合は別の製品への移行、継続中の製品の場合はパッチの適用やバージョンアップにより脆弱性をなくすことが必要だ。
Copyright © ITmedia, Inc. All Rights Reserved.