安全地创建相对java.io.File的方法

Aar*_*lla 8 java security file

如何java.io.File以安全的方式创建相对于父文件夹的实例,即防止恶意攻击者突破父文件夹.

例:

  String path = request.getParameter( "path" );
  File file = new File( folder, path );
Run Code Online (Sandbox Code Playgroud)

这是不安全的,因为攻击者可能会发给我一个../../../etc/passwdas path.

我如何"清理"这样的路径?

Aar*_*lla 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;
}
Run Code Online (Sandbox Code Playgroud)

所以用法是:

File file = new File( folder, path );
if( ! isParent( folder, file ) ) {
    ... deny access ...
}
Run Code Online (Sandbox Code Playgroud)

上面的代码可能不是很快,但所有其他解决方案都有安全问题:

  • 我可以删除,/../|^../|/..$但这在 Windows 上不起作用。对于 Windows,该模式会变得更加复杂,不要忘记 Java/在 Windows 上接受作为文件分隔符(是的,它C:/Windows/是有效的并且与 相同C:\Windows\

    此外,该路径a/../b/c是有效的,因为它不会打破边界,因此仅移除相对运动是不够的。

  • 我可以使用创建两个字符串getCanonicalPath()并确保parent路径是file. 但是,我必须确保父路径之后的字符是文件分隔符(见上文为什么File.SEPARATOR还不够)。