Unrestricted File Download in Java
Vulnerable Example
The snippet below provides a helper function used to concatenate the directory that contains the asset files /opt/wwwdata/assets/
with the file name passed as assetName
.
import java.io.*;
public class Util {
private final static String assetsDir = "/opt/wwwdata/assets/";
public static String getAssetPath(String assetName) {
File path = new File(assetsDir, assetName);
return path.toString();
}
}
If assetName
is controlled by the user, it is possible to conduct a path traversal attack and escape the intended directory, for example, by using ../../../../../../etc/passwd
as file asset name.
This results in the absolute path /opt/wwwdata/assets/../../../../../etc/passwd
which is canonicalized by the operating system as /etc/passwd
.
Prevention
When building the final path, using only the final fragment of the user-provided value is often enough, and the getName()
method of the File
instances does exactly that. So, for example, the utility class becomes:
public class Util {
private final static String assetsDir = "/opt/wwwdata/assets/";
public static String getAssetPath(String assetName) {
String safeAsseName = new File(assetName).getName();
File path = new File(assetsDir, safeAsseName);
return path.toString();
}
}
The previous attack would result in the /opt/wwwdata/assets/passwd
file being read.