IDS50-J. ファイル名には厳しい命名規則を使う
ファイル名やパス名に特定の文字や文字列が含まれていると、問題を引き起こす可能性がある。
- 文字列先頭のダッシュ文字: ファイル名を引数にプログラムが呼び出されるとき、ファイル名の先頭がダッシュ文字だと問題が発生する可能性がある。先頭のダッシュ文字は文字列がプログラムのオプションであると解釈される可能性があるからだ。
- 改行、復帰、エスケープなどの制御文字: ファイル名やログに出力する文字列に制御文字が含まれていると、予期せぬ挙動を引き起こす可能性がある。
- 空白文字: 空白文字を含むファイル名を二重引用符でくくっていない場合、スクリプトの中で問題になる。
- 無効な文字エンコーディング: 文字エンコーディングによってファイル名やパス名の検査が難しくなる場合がある。(「IDS11-J. 文字列の変更はすべて検査の前に行う」を参照)
- 名前空間の接頭辞と慣習: 名前空間の接頭辞がパス名に含まれていると、予期せぬ挙動を招く可能性がある。
- コマンドインタプリタ、スクリプト、パーザ: コマンドインタプリタ、シェル、コマンドパーザで処理される際に特別な意味を持つ文字。
MS-DOS の影響もあり、xxxxxxxx.xxx
(x
は英数字一文字)という 8.3 形式のファイル名は、こんにちのシステムでは正しく扱えると考えてよいだろう。ファイル名の大文字小文字を区別するプラットフォームもあれば、そうでないプラットフォームもある。VU#439395 は、大文字小文字の問題を正しく扱わなかったために発生した脆弱性の例である [VU#439395]。開発者は ASCII 文字集合内の安全な文字のみを使ってファイル名やパス名を生成するべきであり、セキュリティが重要なアプリケーションでは、これらの文字を使った名前のみを受け入れるべきである。
違反コード
以下の違反コード例では、ファイル名の一部に安全に取り扱えない文字が含まれている。
File f = new File("A\uD8AB");
OutputStream out = new FileOutputStream(f);
安全でない文字をどう扱うかはプラットフォームに任されている。たとえば Ubuntu Linux では、このファイル名は以下のようなものとして扱われる。
A?
適合コード
前述のように、ファイル名には ASCII 文字集合のなかで安全に扱われることが明確な文字種のみを使うべきである。
File f = new File("name.ext");
OutputStream out = new FileOutputStream(f);
違反コード
以下の違反コード例では、ユーザからの入力を無害化せずにファイル名として使っている。
public static void main(String[] args) throws Exception {
if (args.length < 1) {
// エラー処理
}
File f = new File(args[0]);
OutputStream out = new FileOutputStream(f);
// ...
}
このコードでは、ファイル名の中に問題を引き起こす文字が含まれていないか検査していない。ファイルを作成したりファイル名を変更するプログラムにこのコードが含まれ、ファイルが後にスクリプトなどの自動化されたプロセスに利用されるということを攻撃者に知られると、後の処理で問題を引き起こすような文字列を入力されてしまうかもしれない。
適合コード
以下の適合コードでは、ホワイトリストを使って安全でない文字を含むファイル名を排除している。ファイル名やディレクトリ名の末尾がピリオドでないことの確認など、さらなる入力値検査が必要な場合もある。
public static void main(String[] args) throws Exception {
if (args.length < 1) {
// エラー処理
}
String filename = args[0];
Pattern pattern = Pattern.compile("[^A-Za-z0-9._]");
Matcher matcher = pattern.matcher(filename);
if (matcher.find()) {
// ファイル名に無効な文字が含まれている。エラー処理。
}
File f = new File(filename);
OutputStream out = new FileOutputStream(f);
// ...
}
例外
IDS50-J-EX0: コマンドインタプリタ、シェル、パーザ、ロガーなど一部の文字に特別な意味を付与する機能において、与えられたファイル名やパス名が使用されないと開発者が判断した場合に限り、プログラムはそれら「安全でない(特別な意味を持つ)」文字を含むファイル名やパス名を受け入れてもよい。
リスク評価
ASCII 文字集合のなかの安全な文字だけを使用しないと、データの誤解釈につながる可能性がある。
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
IDS50-J |
中 |
低 |
中 |
P4 |
L3 |
自動検出
ツール | バージョン | チェッカー | 説明 |
---|---|---|---|
The Checker Framework |
2.1.3 |
Tainting Checker | Trust and security errors (see Chapter 8) |
関連ガイドライン
SEI CERT C++ Coding Standard |
VOID MSC09-CPP. Character encoding: Use subset of ASCII for safety |
ISO/IEC TR 24772:2010 |
Choice of Filenames and Other External Identifiers [AJN] |
CWE-116, Improper encoding or escaping of output |
参考文献
ISO/IEC 646-1991 |
ISO 7-Bit Coded Character Set for Information Interchange |
[Kuhn 2006] |
UTF-8 and Unicode FAQ for UNIX/Linux |
[Wheeler 2003] |
5.4, "File Names" |
[VU#439395] |
翻訳元
これは以下のページを翻訳したものです。
IDS50-J. Use conservative file naming conventions (revision 99)