PHP realpath не работает, чтобы предотвратить обратный путь в каталогах
Я получил чужой код для системы, которая показывает в вашем браузере папки с фотографиями в них.
Например, это возможный URL на сайте:
gallery.php?action=view&folder=Cars
На данный момент вы можете заменить "Cars" на../../../../../, что с радостью покажет корневую папку Linux. К счастью, сайт в данный момент не работает.
Я пытался использовать realpath, чтобы это исправить. Вот что у меня так далеко:
case 'view' :
$name = realpath(dirname(__FILE__) . "/Content/Gallery/" . $_GET['folder']);
echo $name;
$data = $file->getPictures($name);
require 'Views/Gallery.view.php';
break;
Я добавил echo в третью строку, чтобы увидеть, каким будет URL. В приведенном выше URL все хорошо, и echo выводит это:
/var/www/Content/Gallery/Cars
Все идет нормально. Однако, если я введу /../../../../../../../../ вместо "Автомобили", $ name станет /, и на странице все еще будет отображаться корневая папка. Английский не мой родной язык, поэтому я могу неправильно понять, как работает realpath или что он делает. Из того, что я понял, он удаляет любой экземпляр../ из данного URL.
Может кто-нибудь сказать, пожалуйста, что я делаю не так?
2 ответа
Из того, что я понял, он удаляет любой экземпляр../ из данного URL.
Нет, это не то, что он делает. Это не для URL, это для путей. Он просто преобразует путь и расширяет../ в нужную папку. Он не удаляет их, он разрешает их - это означает, что он вычисляет, что означает../, и изменяет путь к этому.
Это также меняет / на \ в Windows.
realpath () раскрывает все символические ссылки и разрешает ссылки на символы "/./", "/../" и дополнительные символы "/" во входном пути и возвращает канонизированный абсолютный путь.
realpath()
одного недостаточно для борьбы с каталогом.
То, что вы описываете, является в точности тем, для чего оно предназначено: оно переводит относительные вещи, такие как ../
в фактический путь к каталогу.
Однако для безопасности вы можете взять realpath()
ed путь и посмотрите , является ли он дочерним по отношению к безопасному базовому пути. Если это не так, то кто-то пытался проникнуть в каталог, в котором нет бизнеса:
$name = realpath(dirname(__FILE__) . "/Content/Gallery/" . $_GET['folder']);
// The safe root directory.
$safe_root = dirname(__FILE__) . "/Content/Gallery/";
// Check whether realpath() result is still inside /Content/Gallery
if (substr($name, 0, strlen($safe_root)) != $safe_root)
die ("Possible directory traversal attack");