9

使用以下代码是否安全:

require($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $_GET['page'] . ".php") 
4

5 回答 5

12

不,它不安全。为什么?

因为两个点的序列/../意味着一个目录返回,攻击者可能会在您的系统上包含任何内容,甚至在$_SERVER['DOCUMENT_ROOT'].. (在一个不幸的配置中,这意味着秘密/敏感的操作系统配置文件。)

您必须使用 IF 或 SWITCH 来获取允许的值以防止恶意输入。例子:

switch($_GET['page']) {
     case 'welcome': $page='welcome';
     case 'shop': $page='shop';
     default: $page='index';
}
require($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $page . ".php")

还要检查一下in_array()是否更容易过滤。

于 2012-07-26T19:44:59.633 回答
2

StackOverflow 有一个关于如何使用 PHP 清理用户输入的有用问答。几年过去了,但原则根本没有改变。

快速的回答是:如果你能从一开始就避免这个问题,你会过得更好。

向我们展示您如何尝试使用它,我们可能会提供改进建议。

于 2012-07-26T19:47:50.860 回答
1

它不安全。您可以使用具有允许值的数组。例如

$allowed_pages = array('index', 'test', 'my_page')
if (!in_array($_GET['page'], $allowed_pages)){
    echo 'good bye';
    die();
} else {
   //
}
于 2012-07-26T19:48:23.800 回答
-1

如果您信任 pages 目录中的所有文件,请尝试:

if (in_array($_GET['page'],glob("/pages/*.php"))) {
   require($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $_GET['page'] . ".php");
} else echo "Nice try hacker!";

这是另一个解决方案,它使用了我用来清理上传文件名的部分功能:

选项 #2 感谢 Daniel,Rok!

$page = preg_replace('/[^a-zA-Z0-9_ %\[\]\.\(\)%&-]/s', '', $_GET['page']);
$filename = $_SERVER['DOCUMENT_ROOT'] . "/pages/" . str_replace("/",'',$page) . ".php";
if (file_exists($filename)) {
    require($filename);
} else echo "Nice try hacker!";

请注意,这仅在文件名中没有特殊字符时才有效

于 2012-07-26T19:54:55.180 回答
-3

使用 regExp 检查你的$_GET['page']!

于 2012-07-26T19:46:24.540 回答