PHP realpath无法阻止目录遍历

yes*_*man 0 php directory-traversal realpath

我收到了其他人的系统代码,该系统在浏览器中显示带有照片的文件夹.

例如,这是网站上可能的网址:

gallery.php?action=view&folder=Cars
Run Code Online (Sandbox Code Playgroud)

目前,您可以用../../../../../替换"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;
Run Code Online (Sandbox Code Playgroud)

我在第三行添加了echo以查看URL是什么.在上面的url中,一切都很好,echo输出:

/var/www/Content/Gallery/Cars 
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是,如果我输入/../../../../../../../../而不是"Cars",$ name变为/并且页面仍显示根文件夹.英语不是我的第一语言,所以我可能误解了真实路径的工作方式或工作原理.根据我的理解,它从给定的URL中删除../的任何实例.

有人可以告诉我我做错了什么吗?

Pek*_*ica 6

realpath() 单独不足以打击目录遍历.

你所描述的是exaclty它的设计目的:它将相关的东西翻译../成实际的目录路径.

但是,为了安全起见,您可以采用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");
Run Code Online (Sandbox Code Playgroud)