9

java.io.File親フォルダーに関連するインスタンスを安全な方法で作成するには、つまり、悪意のある攻撃者が親フォルダーから侵入するのを防ぐにはどうすればよいですか。

例:

  String path = request.getParameter( "path" );
  File file = new File( folder, path );

攻撃者が私に../../../etc/passwdas を送信する可能性があるため、これは安全ではありませんpath

そのようなパスを「きれいにする」にはどうすればよいですか?

4

4 に答える 4

6

他の回答を読んだ後、私はこの解決策を思いつきました:

public static boolean isParent( File parent, File file ) {

    File f;
    try {
        parent = parent.getCanonicalFile();

        f = file.getCanonicalFile();
    } catch( IOException e ) {
        return false;
    }

    while( f != null ) {
        // equals() only works for paths that are normalized, hence the need for
        // getCanonicalFile() above. "a" isn't equal to "./a", for example.
        if( parent.equals( f ) ) {
            return true;
        }

        f = f.getParentFile();
    }

    return false;
}

したがって、使用法は次のようになります。

File file = new File( folder, path );
if( ! isParent( folder, file ) ) {
    ... deny access ...
}

上記のコードはおそらくそれほど高速ではありませんが、他のすべてのソリューションにはセキュリティ上の懸念があります。

  • 削除でき/../|^../|/..$ましたが、Windowsでは機能しません。/Windows の場合、パターンはより複雑になり、Javaが Windows のファイル区切りとして受け入れることを忘れないでください(はい、C:/Windows/有効であり、 と同じ意味ですC:\Windows\) 。

    また、パスa/../b/cは境界を壊さないので有効なので、相対的な動きを取り除くだけでは十分ではありません。

  • を使用して 2 つの文字列を作成し、パスが のプレフィックスであるgetCanonicalPath()ことを確認できます。ただし、親パスの後の文字がファイル区切り文字であることを確認する必要があります (上記の理由を参照してください)。parentfileFile.SEPARATOR

于 2013-04-24T09:53:30.120 に答える
2

/1 つの解決策は、 orで始まるものをすべて禁止すること..です。しかし、「安全で適切な」方法は、(JVM)セキュリティマネージャーを有効にしてアプリケーションを実行し、事前定義された構成外のファイルアクセスを許可しないことだと思います。ただし、セキュリティ マネージャーを有効にするには、ツアー アプリケーションを実行するために必要なすべての権限を把握する作業が必要です。

もちろん、OS ファイルのアクセス許可も重要です。

編集

リクエストに応じて、例を追加しました。例は、Tomcat にデプロイされた現在のプロジェクトからのものです。

grant codeBase "file:${catalina.base}/webapps/mywebapp/-" {
    permission java.io.FilePermission "path/to/folder", "read"; // Anything else will be disallowed
    // Other required permissions
}
于 2013-04-24T07:49:15.470 に答える
1
    String path = "../../../etc/passwd";
    String pureFilename = (new File(path)).getName();
    File file = new File(folder, pureFilename);
于 2013-04-24T07:54:38.550 に答える