2014-09-04 110 views
0

我为我的网站制作了一个简单的文件管理器脚本。Php scandir限制访问

为了列出文件夹中的所有文件和类别,我使用scandir()函数。我有一个包含基本路径的变量,如$path = /var/www/mysite/uploads。然后我有一个函数,它需要带有附加路径的GET变量,如/my/photos/,所以我返回/var/www/mysite/uploads/my/photos的内容。

问题是,如果用户发送../../../,类似的东西,他会上目录树,并将能够观看整个系统。

我该如何限制?我唯一一派whas约chroot,但不知道这是什么,我需要

+0

不要让用户有''../在他们的投入,剥离出来,如果他们已经用它 – 2014-09-04 08:40:56

回答

1

您可以使用realpath()

$storagePath = "/var/www/mysite/uploads"; 
$path = $storagePath . $userPath; 

$path = realpath($path); 
if(strpos($path, $storagePath) === 0){ 
    //Path is okay 
    echo "Okay"; 
} 
else { 
    //User wants to gain access into a forbidden area. 
    echo "Danger"; 
} 

Live demo

说明:由用户提供的路径与存储路径联系。然后使用realpath将此路径转换为absolute path。如果绝对路径从存储路径开始,则一切正常,否则不行。

当然,也可以首先针对RegEx运行用户提供的路径,以确保路径只包含有效字符。

+0

你觉得呢http://stackoverflow.com/questions/3661727 /删除点和斜杠 - 正则表达式非相对这个?使用ltrim?实际上,我编写了像$ path = $ storagePath这样的结果路径。 $ userPath; $ userPath不包含/ var/www/whatever,它只包含像/ my/photos这样的路径的一部分。无论如何strpos不会返回true。但不知道如果与ltrim的解决方案是足够的 – Victor 2014-09-04 09:29:09

+0

@维克特ltrim是肯定的,但我认为这是不够的。为什么不用'$ storagePath替换上例中的$ _GET [“path”]''。 $ userPath'(或'$ path')。然后它将与'strpos'一起工作,不是吗? – idmean 2014-09-04 09:31:34

+0

如果我有?path = ../../../../..,那么结果路径是/var/www/mysite/uploads/../../../../,strpos返回true,因为它在一开始会发现/ var/www/mysite/uploads? – Victor 2014-09-04 09:35:30

0

您总是必须验证用户输入!做一个正则表达式来验证$ _GET ['path']。

此外,您的服务器应该由您的文件系统权限非常低的用户运行。

0

您必须回答的第一个问题是您为什么要从用户路径接受。

之后,如果真的需要,您必须保护您的输入绝对路径或使用..就可以了。

的东西,如

$project_path = realpath($project_path); 
$realpath = realpath($user_input); 
if (str_pos($realpath, $project_path) !== 0) { 
    throw Exception('Security perimeter violation!'); 
} 
+0

我接受一条路径,因为如果用户想要探索一些他需要的文件夹发送文件夹名称。如果文件夹包含在其他文件夹中,则会变成'/ my/photos /',所以我给用户$ path的内容。'/ my/photos /'。我发现你和wumm都使用realpath,感谢你的帮助,看起来正是我需要的 – Victor 2014-09-04 08:51:25

+0

太棒了!看起来很好的理由;) – mcuadros 2014-09-04 08:54:22