Безопасная версия пути.Комбинировать
-
03-07-2019 - |
Вопрос
У меня есть rootPath
которому я доверяю, и relativePath
этого я не знаю.Я хочу объединить их таким образом, чтобы я мог быть уверен, что результат находится под контролем. rootPath
и что пользователь не может использовать ..
чтобы вернуться к исходной точке.Я делай хотите, чтобы относительный путь позволял такие вещи, как: hello\..\world
== world
Решение
Для расширения:используйте Path.Объедините, затем вызовите GetFullPath для результата и убедитесь, что этот результат начинается с rootPath .
Это не защитит вас от жестких ссылок, но должно улавливать простые вещи, такие как двойные точки.
приведенное выше в виде кода:
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");
}
Другие советы
Ты мог бы просто позвонить Path.GetFullPath()
и проверьте, начинается ли он с вашего доверенного rootPath
.Если вы склонны к паранойе, проверьте также, что rootPath
укореняется.
public Boolean IsPathSafe(String rootPath, String relativePath)
{
return rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
Path.IsPathRooted(rootPath) &&
Patch.Combine(rootPath, relativePath).GetFullPath().StartsWith(rootPath);
}
Объяснение первого теста смотрите в комментарии Алекса Мартелли к ответу technophile.
Одна вещь, которую вы можете сделать, это подсчитать количество обратных косых черт (\
) и двойные точки (..
), и убедитесь, что количество двойных точек меньше, чем количество обратных косых черт.Для того, чтобы подняться над rootPath
в вашей структуре папок вам понадобится по крайней мере столько же обратных косых черт, сколько двойных точек - таким образом, если вы разрешите только relativePath
используя хотя бы еще одну обратную косую черту, вы должны быть в безопасности.