安全动态包含

时间:2009-07-06 19:08:35

标签: php security

我一直在我的网站上使用这个php动态包含代码。但我认为这不安全,如何编写更安全,更好的代码来取代它:

$page = (empty($_GET['page'])) ? '' : $_GET['page'].".html";

if (empty($page))
{ 
 $page = 'index.html';
}

else
 {
 $page = $page;

 }

 include($page);

非常感谢

6 个答案:

答案 0 :(得分:9)

在安全性方面,总是允许政策是一个糟糕的政策。不要认为请求有效且安全。总是拒绝提前,并使用白名单:

switch($_GET['page']): 
   case 'page-a': case 'page-b': case 'other-page':
      include $_GET['page'] . '.html';
      break;
    default: 
      include 'index.php';
endswitch;

如果白名单很难维护,请尝试将可能性缩小到单一路径,使用basename:

$name = basename($_GET['page']);
include 'includes/' . $name . '.html';

这样您就不必担心安全性,只要您保持此目录(以及所有包含路径)的所有内容都是安全的(请注意,有人可以将受感染的文件上载到该目录)。

如果上述操作失败,请尝试使用realpath()并确保该文件位于指定的目录树中。

答案 1 :(得分:1)

您可以使用preg_replace()确保页面名称不包含任何有害内容:

// $page can only contain letters, numbers and '_'
$page = preg_replace('/[^a-zA-Z0-9_]/', '', $_GET['page']);
include "pages/$page.html";

答案 2 :(得分:0)

您可以定义某种白名单,以确定允许以这种方式包含哪些文件,并在执行包含之前检查该列表。

另一种方法是只允许包含在某个目录(或子目录)中,并验证所请求的文件是否在该目录中。

答案 3 :(得分:0)

我建议,检查$ page var中的无效文件字符(即\ /:*<>?),并使用php的file_exists()方法检查文件是否存在。

这样的东西
$bad_chars = array("\\", "/", ":", "*", "?", ">", "<", "Foo", "Bar");
$file = str_replace($bad_chars, "", $file);

if (!file_exists('/' . $file))
{
    echo 'bad file name';
}

答案 4 :(得分:0)

当有人在页面参数中添加“http://example.com/unsafe_file”时会发生什么?您的脚本可能会出去并愉快地下载远程不安全脚本,然后执行它在那里找到的任何PHP代码。除其他外,这可能包括拥有您的服务器的漏洞。或者打印数据库密码。或透露敏感信息。最重要的是,这种包含绝对不安全,不应该使用。

相反,您应该使用页面白名单来允许和检查参数,或者从数据库中检索页面内容。但是不应该只使用包含文件。

答案 5 :(得分:0)

一般情况下,我不会使用未经过授权的用户输入对includerequire进行任何调用。这太危险了。如果用户请求的文件位于Web根目录之外,该怎么办?

您应该使用白名单限制可以包含的内容,或者不需要用户输入其他强大的调用,例如includerequire。否则,您自己打开Remote File Inclusion attacks。有一些方法可以通过禁用allow_url_fopen来缓解RFI,但最好只是完全避免这种情况。