How do I create a java.io.File
instance relative to a parent folder in a secure way, i.e. preventing a malicious attacker from breaking out of the parent folder.
Example:
String path = request.getParameter( "path" );
File file = new File( folder, path );
this is unsecure since the attacker might send me a ../../../etc/passwd
as path
.
How do I "clean" such a path?
After reading the other answers, I came up with this solution:
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;
}
So the usage would be:
File file = new File( folder, path );
if( ! isParent( folder, file ) ) {
... deny access ...
}
The code above probably isn't very fast but all other solutions have security concerns:
I could remove /../|^../|/..$
but that wouldn't work on Windows. For Windows, the pattern would become more complex and don't forget that Java accepts /
as file separator on Windows (yes, C:/Windows/
is valid and means the same as C:\Windows\
)
Also, the path a/../b/c
is valid since it doesn't break the boundary, so just removing the relative movements isn't good enough.
I could create two strings using getCanonicalPath()
and make sure the parent
path is a prefix of file
. But then, I'd have to make sure the character after the parent path is a file separator (see above why File.SEPARATOR
isn't enough).
One solution would be to disallow anything that starts with I guess the "secure/proper" way is to run your application with a (JVM) security manager enabled and disallow file access outside the predefined configuration. But enabling a security manager requires some work figuring out all the permissions you need to be able to run tour application. /
or ..
. But
OS file permissons are also important, obviously.
Edit
Added an example, as requested. Example is from a current project deployed in Tomcat:
grant codeBase "file:${catalina.base}/webapps/mywebapp/-" {
permission java.io.FilePermission "path/to/folder", "read"; // Anything else will be disallowed
// Other required permissions
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With