Ho scoperto che alcuni URL quando vengono passati direttamente per FilenameUtils.getName
restituire risultati indesiderati e questo deve essere concluso per evitare exploit.
Per esempio,
System.out.println(FilenameUtils.getName("http://www.google.com/.."));
ritorna
..
che dubito che chiunque voglia permettere.
La seguente funzione sembra funzionare correttamente e mostra alcuni di questi casi di test e ritorna null
quando non è possibile determinare il nome file.
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;
}
}
Questo è racchiuso in alcuni semplici casi di test nel seguente esempio:
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;
}
}
}