TOP設計・移行・活用> はじめに
脆弱なWebアプリケーション
脆弱なWebアプリケーション

第5回:インジェクション攻撃
著者:セントラル・コンピュータ・サービス  長谷川 武
2005/5/25
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


INDEX
第5回:インジェクション攻撃
はじめに
  マルチプルステートメント
  シングルクォートのエスケープ
  OSコマンドインジェクション