 |
|
1 2 3 4 次のページ
|
 |
はじめに
|
今回はWebアプリケーションの脆弱性における4番目のカテゴリー「インジェクション攻撃」について解説する。
※注意:
この記事にはWebアプリケーションの脆弱性を解説する必要上、攻撃手口に関する情報が含まれています。これらの手口を他者が運営するWebサイトに向けて仕掛けると、最悪の場合刑事罰および損害賠償請求の対象となります。脆弱性の調査・検証は、必ずご自身の管理下のコンピュータシステムおよびローカルエリアネットワークで行ってください。この記事を参考にした行為により問題が生じても、筆者およびThinkIT編集局は一切責任を負いません。
|
インジェクション攻撃
|
インジェクション(injection)とは、内部に何かを注入することを意味する言葉だ。インジェクション攻撃とは、プログラムがごく普通に受け取る入力データの中にセキュリティを侵害するようなコマンドを巧みに混入し、それをコンピュータ内部で機能させてしまう攻撃手口のことをいう。
インジェクション攻撃の中で最も代表的なものには、データベースに干渉して情報漏えい・情報改ざんを引き起こすSQLインジェクション攻撃がある。そのほかにも、シェルに干渉するOSコマンドインジェクション、XML検索条件をかく乱するXPathインジェクション、ディレクトリ検索条件に干渉するLDAPインジェクションといった攻撃手口が知られている。
図1:バックエンドで「発火」するインジェクション攻撃 (画像をクリックすると別ウィンドウに拡大図を表示します)
ここでは、SQLインジェクション攻撃を中心に見ていこう。
|
SQLインジェクション攻撃
|
本格的なWebアプリケーションの場合、たいていその背後でSQLによりアクセスされるデータベース管理システムが稼働している。SQLは、データベースへのアクセスに使われるプログラミング言語の定番である。
Webアプリケーションは、データを検索したり更新したりするSQL文を文字列の形で用意して、それをデータベースエンジンに投入することでデータへのアクセスを実現している。
たとえば、商品テーブルを検索して商品コードから商品名と価格を得るSQL文は次のような感じだ。
データベース検索を行うSQL文の例
SELECT name, price FROM product_table WHERE code='A123'
これをJavaプログラムの中から発行するには、たとえば次のようなコードを書くことになる。
プログラムからSQL文を発行する例(Java)
String parameter = ユーザが入力した値;
Connection c = データベース接続オブジェクトの取得;
Statement st = c.createStatement();
String sql = "SELECT name, price FROM product_table WHERE code='" + parameter + "'";
ResultSet rs = st.executeQuery(sql); // 検索を実行。rsに結果が得られる
|
 |
攻撃の基本形
|
このようにしてSQL文を組み立てることは、実はとても危険なことである。たとえば次の例を見ていただきたい。これはログインの場面で、ユーザからユーザIDとパスワードを受け取り、それらが正しいかどうか判定するコードの一部だ。変数uidとpwはそれぞれユーザIDとパスワードの値を保持しており、これら2つと同じ値の組み合わせがテーブルaccount_tableの中に登録されていればログインを許すというものだ。
ログイン処理の例(Java)
Statement st = connection.createStatement();
// SQL文のためのオブジェクトを確保
String sql = "SELECT uid FROM account_table WHERE uid='" + uid + "' AND pw='" + pw + "'"
// ユーザ入力を埋め込んでSQL文の文字列を作る
ResultSet rs = st.executeQuery(sql);
// 検索を実行。rsに結果が得られる
if (rs.next()) { // 該当するデータがDB中に存在する
// ログインOK
}
このロジックはユーザIDに次のような特別な値を指定することで簡単に攻略できてしまう。
攻撃入力:' OR 1=1--
なぜなら、この入力値が埋め込まれた状態のSQL文は次のような形になるからである。
干渉されてできたSQL文
SELECT uid FROM account_table WHERE uid='' OR 1=1--' AND pw='任意の文字列'
このuidに対する攻撃入力は、次の3つの要素からできている。
|
要素 |
攻撃の効果 |
' |
文字列定数の外に出る |
OR 1=1 |
常にTRUEとなるよう、検索条件をねじ曲げる |
-- |
それ以降の内容をコメントとして無視させる |
|
表1:SQLインジェクション攻撃要素
|
最初の攻撃要素は、入力データの先頭に仕込まれたシングルクォート文字「'」だ。これはSQL文の中で文字列定数を囲む記号として用いられるものだが、それをわざとデータに混入することで文字列定数を終わらせてしまい、攻撃者が与えた文字列がSQL文の文法要素として働くように仕向けるものである。
uid='' 攻撃者が与える文字列…
次の攻撃要素は、WHERE句の論理式の意味を変えるための「OR 1=1」である。1=1は論理値TRUE(常に真)の代わりに使っている。データベースエンジンによってはTRUEという定数を受け付けないものもあるが、1=1という式なら受け入れられるからだ。つまりWHERE句の論理式を下記のようにして、常に条件が成立するようにねじ曲げてしまう。
何らかの式 OR TRUE
最後の攻撃要素は、コメント記号「--」である。この記号は、それ以降の記述内容はコメントと見なせ、という意味を持つ。攻撃者は、自分の与えたSQL文の断片の方をデータベースエンジンに処理させ、プログラマが用意した本来のSQL文をコメントとして無視させてしまうのだ。
※補足:
この例は説明を簡単にするために用意したものであり、ユーザ認証処理としてはかなりできが悪いことにご注意願いたい。パスワードを平文でデータベースに格納すべきでないし、データベース検索結果の行数がちょうど1であることを確認すべきである。
|
1 2 3 4 次のページ
|

|
|

|
著者プロフィール
セントラル・コンピュータ・サービス株式会社 長谷川 武
シニア・セキュリティ・スペシャリスト、IPA 非常勤研究員。2002年にはIPA ISEC『セキュア・プログラミング講座』の制作ディレクターをつとめた。これを契機に、現在は勤務先とそのパートナー企業を通じてセキュアプログラミングセミナー/実習/スキル評価テストといった教育サービスを「TRUSNET(R)アカデミー」として提供している。問い合わせE-mail:info@trusnet.com。
|
|
|
|