Dec 09, 2005

[Misc] File アクセス時における Unicode の取り扱いについて

遅ればせながら、産総研グリッド研究センター 高木浩光さんによる「安全なWebアプリ開発の鉄則2005」を読んだ。 その中に実は全く認識していなかった問題があったので、Java の環境で実際に起こり得るのか確かめてみた。 「安全なWebアプリ開発の鉄則」の 2005 年度版は Web 上で公開されていないようなので、↓は 2004 年度版へのリンク。 同様の記述は既に記載されている。

安全なWebアプリ開発の鉄則2004
http://www.nic.ad.jp/ja/materials/iw/2004/proceedings/T5.pdf

実験内容

"c:\tmp\dummy.txt\u0000.html" というファイルを読み込んだ際に、ファイルシステム上で実際に読み込まれるのはどのファイルなのかをチェックする。 拡張子を String#endsWith でチェックして・・・というのはありがちな処理。 "c:\tmp\dummy.txt" が読み込まれてしまうと拡張子チェックをすり抜けてしまうことになるので、セキュリティホールの原因になる。

実験環境

  • Windows XP Professional
  • Java 1.5.0_05
  • c:\tmp\dummy.txt を作成し "this file is c:\tmp\dummy.txt" と書き込んである
  • c:\tmp には dummy.txt 以外のファイルは存在しない

サンプルコード

public static void main(final String[] args) throws IOException {

    String fileName = "c:\\tmp\\dummy.txt\u0000.html";
    File file = new File(fileName);

    System.out.println("Exists: " + file.exists());
    System.out.println("Absolute Path: " + file.getAbsolutePath());
    System.out.println("ends with \".html\": " + file.getAbsolutePath().endsWith(".html"));

    FileReader fr = null;
    BufferedReader br = null;
    try {
        fr = new FileReader(fileName);
        br = new BufferedReader(fr);
        String line = null;

        System.out.println();
        while ((line = br.readLine()) != null) {
            System.out.println("" + line);
        }
    } finally {
        try {
            if (br != null) {
                br.close();
            }
        } finally {
            if (fr != null) {
                fr.close();
            }

        }
    }
}

実行結果

Exists: true
Absolute Path: c:\tmp\dummy.txt□.html
ends with ".html": true

this file is c:\tmp\dummy.txt

・・・というわけで

パスに '\u0000' が入ると、JVM と OS で認識するファイルが異なってしまうことが分かった。 ユーザ入力の文字列をパスの一部として利用するような場合は注意が必要となる。

それにしても、あっさりと自分の認識不足が露呈してしまったorz ファイル名をユーザー入力にする場合はかなり気をつけねば。

Posted in Misc | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |