2013-04-17 35 views
0

包含从查询字符串获取文件夹和文件名的文件的最佳方式是什么?php包含来自查询字符串的可变文件

myServer.com/data有数百个文件夹中有几个文件。 这些是纯html文件。

myServer.com/code是一个PHP targetPage.php

我可以建立一个这样的URL:

http://www.myServer.com/code/targetPage.php?folder=folder132&name=file23 

什么是阅读中的源文件的PHP源文件夹,并将源“div”的内容作为targetDiv的innerHTML包含在目标页面中?

<body><div id="targetDiv">This is the place holde div</div> 

我对PHP比较陌生,因此是个问题。

+2

请不要这样做。这个脚本产生很大的安全问题。 –

+1

“文件夹”参数始终是单个名称还是可以具有目录分隔符? –

+1

攻击者可以将php脚本添加到任何文件类型而不更改MIME类型和扩展名。他可以执行该操作。请检查此链接http://security.stackexchange.com/questions/32967/is-it-possible-to-execute-a-php-script-in-an-image-file –

回答

1

首先,让绝对确定包含的文件是允许的,最好是使用whitelist

然后,您可以使用像file_get_contents()这样的函数将文件读取到字符串中并使用echo输出。

为了结束(这是一个办法做到这一点,还存在其他途径):

$file = $_GET['folder']."/".$_GET['file']; 

if (in_array($file, $whitelist)) { 
    $contents = file_get_contents($file); 
} else { 
    $contents = "Not allowed"; 
} 

echo "<body><div id='targetDiv'>$contents</div>" 

例如,您可以通过扫描你希望能够以显示目录生成的白名单。 (这不在这个答案的范围之内;-))。

另一种解决方案可能是使用realpath()检查规范结果路径。

+0

我并不是说不可能使这项工作具有一定的安全性,但我敢打赌,有一些方法可以在已经构建的结构中完成同样的事情,通过在请求映射到期望的文件,然后完全不公开给访问者的PHP代码会将其转换为适当的文件引用。 – Craig

+0

@Craig - Exactement,mon ami :-) –

+0

@Craig我同意,但海报声明他有几百个文件夹,可能由一些其他程序生成。生成ID意味着有另一个任务,更多的代码,因此更多的错误。我建议的基本上是使用文件夹和文件名作为它们的ID并将它们映射到文件。 –

1

这基本上是对潜在黑客的邀请,他们毫无疑问会感谢您让他们能够轻松指定哪些文件包含在PHP页面中(并因此执行)。

乍一看,这至少与导致SQL注入攻击的问题类似。你真的确定你想从查询字符串中获取包含文件的路径吗?查询字符串暴露给最终用户。我看到的一个问题是,这往往会将访问者的网站内部结构暴露出来。另一个问题是,作为访问者,我可以试验不同的包含文件,直到我大概发现某个以某种方式(最好)或(最坏的情况下)破坏网站的人破坏您的安全并给予我更大的访问权限到你的服务器或你的数据库,这会让我更深入地了解你的系统,直到我完全受损,或者能够删除或更新你不想让我的数据库中的东西。通过“我”和“我”,当然我假设有人试图破解你的网站。

我会探索找到一个不同的(服务器端,不暴露给访客)的方式来找出哪个文件包含。

+1

如何在没有SQL的情况下进行SQL注入? –

+0

那么,在这种情况下,它会是PHP注入,是吗?不过,相同的基本概念。 :-) – Craig

+0

我认为没有危险,因为查询字符串不会是明确的:它将包含类似于“?paramA = 123?paramB = 12”的东西,而不是显式路径。使用“123”,我将设置文件夹路径并使用paramB文件名。 –

0

如果该文件夹应该只是一个没有目录分隔符的名称,则可以使用basename()从文件夹和名称中去除分隔符。该文件夹需要特殊处理,因为..在技术上是有效的,但您不希望允许超出您的基本目录。

if (isset($_GET['folder'], $_GET['name'])) { 
    $folder = trim(basename($_GET['folder']), '.') ?: '.'; 
    $name = basename($_GET['name']); 

    $file = BASE_DIR . "/$folder/$name"; 
    if (is_file($file) && is_readable($file)) { 
     echo file_get_contents($file); 
    } 
} 

BASE_DIR将包含从中加载文件的基本目录的常数。

+0

PHP中有一个'realpath'函数,它给你实际的路径,没有点和所有的。 –

+0

@BartFriederichs是的,但是很好地给出'../../../../ etc/passwd'的绝对路径:)即不安全。 –

+0

不,'realpath('../../../../ etc/passwd')'是'“/ etc/passwd”'。 –