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() одного недостаточно для борьбы с каталогом.

То, что вы описываете, является в точности тем, для чего оно предназначено: оно переводит относительные вещи, такие как ../ в фактический путь к каталогу.

Однако для безопасности вы можете взять 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");
Другие вопросы по тегам