なぜPHPアプリにセキュリティホールが多いのか?

第27回 見過ごされているWebアプリケーションのバリデーションの欠陥

この記事を読むのに必要な時間:およそ 3 分

今回解説するWebアプリケーションのバリデーションの欠陥はPHPに限った問題ではありません。多くのプラットフォームのWebアプリケーションで見過ごされているバリデーション仕様の欠陥です。それは文字エンコーディングのチェックです。

文字エンコーディングバリデーションの必要性

筆者の知る限りでは,2004年に相次いで今まで知られていなかったアタックベクタ(攻撃経路)が見つかりました。2004年に多く見つかった新しいアタックベクタとは不正な文字エンコーディングを利用した攻撃です。不正な文字列を利用したJavaScriptインジェクションやSQLインジェクションの攻撃手法が公開されました。

文字エンコーディングを利用した攻撃自体は当時でも新しい攻撃手法ではありませんでした。文字エンコーディングを利用した攻撃は,少なくとも2000年から広く知られていた攻撃手法でした。ブラウザが文字エンコーディングを自動的に識別する仕様を用いたインジェクション攻撃は,2000年初めには,少なくとも一部のハッカーには,割と広く知られていた攻撃手法でした。

意図している通りの正しい文字エンコーディングが利用されているか確認することの重要性は随分昔から「セキュリティ維持に必須」の確認であると認識されているべき問題でした。

データベースシステムの場合

データベースシステムの場合,2005年に文字エンコーディングを利用したSQLインジェクション問題が認識され,その対策としてほとんどのデータベースシステムで文字エンコーディングのバリデーションコードが追加されました。

以来,マルチバイト文字をサポートするDBMSは保存されている文字列が正しい文字エンコーディングであるかチェックした後,文字列データを保存するようになっています。不正な文字エンコーディングの場合,エラーでSQLが実行できないようになっています※1)。

※1

しかし,設定やエスケープ方法によってはシステムが持っているチェック機能が役に立たないこともあります。

文字エンコーディングバリデーションの重要性に対する無理解

現在でも,文字エンコーディングが正しいエンコーディングであるか確認することがセキュリティ上とても大切なバリデーションである,と正しく認識していない開発者が数多く居ます。日本語のようにマルチバイト文字を使用する国の開発者であっても,文字エンコーディングを入力時にバリデーションする重要性を正しく理解していないことも少なくありません。

シングルバイト圏の開発者に,文字エンコーディングのバリデーションの重要性を理解してもらうのはさらに困難です。にも関わらず多くのWebアプリケーションはシングルバイト圏で開発され,それらのWebアプリケーションを参考にマルチバイト圏の開発者も開発しているため,ほとんどのWebアプリケーションで文字エンコーディングのチェックが行われていません。

文字エンコーディングを正しく扱わないリスク

データベースシステムの場合,正しく文字エンコーディングを扱わないと,SQLインジェクション,XPathインジェクション等が可能となる場合があります。

Webアプリケーションの場合,さらに多くのリスクがあります。

  • SQL/XPathインジェクション
  • Frame/JavaScript/HTML/CSS/オブジェクトインジェクション
  • JavaScriptのバッファーオーバーフロー
  • XMLインジェクション
  • XML処理系のバッファオーバーフロー(XSLTなど)
  • 文字エンコーディング認識を利用したJavaScript実行
  • その他,文字列を処理する箇所すべて

これらの攻撃が文字エンコーディングを利用して行われる可能性があります。

不正な文字エンコーディングの利用を許してしまうと,Webアプリケーション内部で問題が発生しなくても,システム全体のどこで問題が発生するか分からなくなります。ブラウザ,外部のXML処理系,バッチ処理など,文字エンコーディングを利用した攻撃のリスクを残すことになります。

システムへ与える影響を考えれば,アプリケーションが文字エンコーディングが正しいがチェックしなければならないことは明らかです。

文字エンコーディングのバリデーション

ユーザからの入力チェックは入力を受け入れるアプリケーションの責任です。出力を受け入れるアプリケーションが正しく処理できるよう,正しい文字エンコーディングで出力することは文字列を出力するアプリケーションの責任です。

ユーザが正しい文字エンコーディングで出力してくれる,などという仮定は絶対にできません。いい加減な文字エンコーディングで出力しても,出力先のアプリケーションで正しく処理してくれる,などと仮定することも絶対にできません※2)。

※2

文字エンコーディングのバリデーションとは異なる問題ですが,SJIS等の場合,出力側のアプリケーションが正しくエスケープ処理していないと,受け入れ側のアプリケーションでは問題をまったく検出できない場合があります。

文字エンコーディングのチェックは,ほかのセキュリティチェックと同様に,ブラックリスト方式でチェックするのではなく,ホワイトリスト方式でチェックする方法が利用できる場合はホワイトリスト方式でチェックします。

チェックは必ずリクエスト処理の最初に行われる入力バリデーション処理で行い,不正な文字エンコーディングを検出した場合にはリクエスト処理をエラーにして終了させます。サニタイズして処理を継続してはいけません。不正な文字エンコーディングの不都合がある部分だけを取り除くと,別の問題が発生する場合があるからです。

PHPの場合,文字エンコーディングが正しい文字エンコーディングであるかチェックするための関数,mb_check_encoding関数を利用して,入力チェック時にすべての文字列の文字エンコーディングが期待している文字エンコーディングとして妥当であるかチェックします。

入力のバリデーション例

<?php
function _validate_encoding($val, $key) {
    if (!mb_check_encoding($key) || !mb_check_encoding($val)) {
        trigger_error('Invalid charactor encoding detected.');
        exit;
    }
}
$vars = array($_GET, $_POST, $_COOKIE, $_SERVER, $_REQUEST);
array_walk_recursive($vars, '_validate_encoding');

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書

コメント

コメントの記入