Versión segura de Path.Combine
-
03-07-2019 - |
Pregunta
Tengo un rootPath
en el que confío y un relativePath
que no tengo. Quiero combinarlos de tal manera que pueda estar seguro de que el resultado está en rootPath
y que el usuario no puede usar ..
para volver más allá del inicio punto. do quiero que la ruta relativa permita cosas como: hello \ .. \ world
== world
Solución
Para expandir: use Path.Combine, luego llame a GetFullPath en el resultado y verifique que ese resultado comience con rootPath.
No te protegerá contra enlaces duros, pero debería detectar cosas simples como puntos dobles.
el código anterior:
string Resolve(string fileName)
{
string root = FileRoot();
string ret = Path.GetFullPath(Path.Combine(root, fileName));
if (ret.StartsWith(root.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar)) return ret;
throw new ArgumentException("path resolved to out of accesable directroy");
}
Otros consejos
Puede llamar a Path.GetFullPath ()
y verificar si comienza con su rootPath
de confianza. Si tiendes a la paranoia, comprueba también que rootPath
está enraizado.
public Boolean IsPathSafe(String rootPath, String relativePath)
{
return rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
Path.IsPathRooted(rootPath) &&
Patch.Combine(rootPath, relativePath).GetFullPath().StartsWith(rootPath);
}
Para una explicación de la primera prueba, vea el comentario de Alex Martelli sobre la respuesta del tecnófilo.
Una cosa que puedes hacer es contar el número de barras invertidas ( \
) y los puntos dobles ( ..
), y asegurarte de que el número de dobles los puntos son más pequeños que la cantidad de barras invertidas. Para ir por encima de rootPath
en su estructura de carpetas, necesitará al menos tantas barras diagonales invertidas como puntos dobles, por lo tanto, si solo permite relativePath
con al menos Una barra invertida más, debería estar seguro.