Ответ ircmaxell не был полностью правильным. Я видел это решение в нескольких фрагментах, но в нем есть ошибка, связанная с выводом realpath()
. Функция realpath()
удаляет конечный разделитель каталогов, поэтому представьте два смежных каталога, таких как:
/foo/bar/baz/
/foo/bar/baz_baz/
Так как realpath()
удалит последний разделитель каталогов, ваш метод вернет "хороший путь", если $_GET['path']
будет равно "../baz_baz", поскольку это будет что-то вроде
strpos("/foo/bar/baz_baz", "/foo/bar/baz")
Может быть:
$basepath = '/foo/bar/baz/';
$realBase = realpath($basepath);
$userpath = $basepath . $_GET['path'];
$realUserPath = realpath($userpath);
if ($realUserPath === false || strcmp($realUserPath, $realBase) !== 0 || strpos($realUserPath, $realBase . DIRECTORY_SEPARATOR) !== 0) {
//Directory Traversal!
} else {
//Good path!
}