Saya telah menemukan bahwa beberapa url ketika disahkan langsung untuk FilenameUtils.getName
mengembalikan hasil yang tidak diinginkan dan ini perlu dibungkus untuk menghindari eksploitasi.
Sebagai contoh,
System.out.println(FilenameUtils.getName("http://www.google.com/.."));
kembali
..
yang saya ragu ada orang yang mau mengizinkan.
Fungsi berikut tampaknya berfungsi dengan baik, dan menunjukkan beberapa kasus uji ini, dan kembali null
ketika nama file tidak dapat ditentukan.
public static String getFilenameFromUrl(String url)
{
if (url == null)
return null;
try
{
// Add a protocol if none found
if (! url.contains("//"))
url = "http://" + url;
URL uri = new URL(url);
String result = FilenameUtils.getName(uri.getPath());
if (result == null || result.isEmpty())
return null;
if (result.contains(".."))
return null;
return result;
}
catch (MalformedURLException e)
{
return null;
}
}
Ini dibungkus dengan beberapa test case sederhana dalam contoh berikut:
import java.util.Objects;
import java.net.URL;
import org.apache.commons.io.FilenameUtils;
class Main {
public static void main(String[] args) {
validateFilename(null, null);
validateFilename("", null);
validateFilename("www.google.com/../me/you?trex=5#sdf", "you");
validateFilename("www.google.com/../me/you?trex=5 is the num#sdf", "you");
validateFilename("http://www.google.com/test.png?test", "test.png");
validateFilename("http://www.google.com", null);
validateFilename("http://www.google.com#test", null);
validateFilename("http://www.google.com////", null);
validateFilename("www.google.com/..", null);
validateFilename("http://www.google.com/..", null);
validateFilename("http://www.google.com/test", "test");
validateFilename("https://www.google.com/../../test.png", "test.png");
validateFilename("file://www.google.com/test.png", "test.png");
validateFilename("file://www.google.com/../me/you?trex=5", "you");
validateFilename("file://www.google.com/../me/you?trex", "you");
}
private static void validateFilename(String url, String expectedFilename){
String actualFilename = getFilenameFromUrl(url);
System.out.println("");
System.out.println("url:" + url);
System.out.println("filename:" + expectedFilename);
if (! Objects.equals(actualFilename, expectedFilename))
throw new RuntimeException("Problem, actual=" + actualFilename + " and expected=" + expectedFilename + " are not equal");
}
public static String getFilenameFromUrl(String url)
{
if (url == null)
return null;
try
{
// Add a protocol if none found
if (! url.contains("//"))
url = "http://" + url;
URL uri = new URL(url);
String result = FilenameUtils.getName(uri.getPath());
if (result == null || result.isEmpty())
return null;
if (result.contains(".."))
return null;
return result;
}
catch (MalformedURLException e)
{
return null;
}
}
}