2010-06-08 73 views
3

我有一个php脚本,它通过$_GET获取相对路径名,读取该文件并创建它的缩略图。我不希望用户能够从服务器读取任何文件。只有来自某个目录的文件应该被允许,否则剧本应该exit()

这里是我的文件夹结构:

files/ <-- all files from this folder are public 
my_stuff/ <-- this is the folder of my script that reads the files 

我的脚本通过mydomain.com/my_stuff/script.php?pathname=files/some.jpg访问。什么不应该被允许e。摹:mydomain.com/my_stuff/script.php?pathname=files/../db_login.php

所以,这里是脚本的文件夹my_stuff相关部分:

... 
$pathname = $_GET['pathname']; 
$pathname = realpath('../' . $_GET['pathname']); 

if(strpos($pathname, '/files/') === false) exit('Error'); 
... 

我真的不知道有关的做法,似乎并不对我来说是安全的。任何人有更好的主意?

回答

2

这个怎么样(它处理的情况下,当你移动的服务器,因为没有硬编码绝对路径):

$pathname = realpath('../' . $_GET['pathname']); 
$rootpath = realpath('../files/'); 

if (strpos($pathname, $rootpath) !== 0) exit('Error'); 
3

我会先做一个realpath()(解析任何“../”和其他引用),然后检查结果是否是允许的子目录。

以你的情况(我不明白为什么你需要使用的文件/在这种情况下,如果它是被允许的唯一目录,但无论如何):

$basedir = "/etc/www"; 
$allowed = "/etc/www/files"; 

$pathname = realpath($basedir."/".$_GET["pathname"]); 

if (!$pathname) 
die ("Unknown file path"); 

// Check whether $pathname begins with $allowed (= is a sub-directory) 
if (substring($pathname, 0, strlen($allowed)) != $allowed) 
die ("illegal access!"); 

据我所看到的,这应该是一个安全的方法。

+0

任何想法如何以编程方式设置$ basedir和$允许脚本在具有不同路径的不同服务器之间移植? – Max 2010-06-08 13:26:42

+0

@Max啊欢迎来到我的回答:) – 2010-06-08 13:27:21

0

我已经这样做过
basedir被定义为脚本所在的目录。

$basedir=dirname(__FILE__)."/"; 
$systemdir=realpath($_SERVER['DOCUMENT_ROOT'].$dir)."/"; 
if (substr($systemdir,0,strlen($basedir)) !== $basedir) { 

...但佩卡是快:)

+1

唯一要注意的是,不同的实现(FastCGI,mod_php,前端服务器等)对待DOCUMENT_ROOT的方式不同。如果这是一次性脚本,它可能不是问题。但如果这是别人将要使用的东西,不要依赖它... – ircmaxell 2010-06-08 13:58:40

+0

好点我一直忘记它 – 2010-06-08 14:17:27

0

我也将检查./../$_GET['pathname']中的存在,因为这些将是他们不应该去的地方的明显尝试。确实realpath使它安全(因为...是“已解决”),但strpos检查可能在某些(可能是越野车)情况下很弱,其中/files/字符串可能稍后出现,但在访问实际文件时将被忽略,例如一个假想的技巧,比如

/site/my_stuf/secretfile.txt /files/

(使用这样的字符串来访问一个文件应该“看”,即“secretfile.txt”(包括空格)是不是一个目录名,一切都应该失败......但正如所说,这个假设可能是在一个错误的情况下真实的,如果这些技巧利用其他一些不太假设的错误...当然这是不知道的util它被利用)

所以我重复我的建议,特别是检查../ GET字符串;并且为什么不将这个字符串解释为从files开始的路径,即,将files/预加载到用户提供的任何内容,并且如已经说过的那样避免存在../

我不知道是否所有这些都是偏执的(或更好的解决方案存在),但我已经使用了类似的方法为基于URL的目录/文件列表,它允许“直接”访问站点的子目录我的,我当然想要确保没有办法摆脱那个目录。

0

注意:使用实时路径提供的答案是可以的,但是他们应该提到实际路径在所有服务器变体中的工作方式都不一样。