安全性和包含基于URL数据

时间:2010-01-29 11:36:41

标签: php security include

以下包含声明是否存在安全风险?

include "pages/".$_GET["page"].".php";

如果是:
- 为什么? - 什么是更安全的方法?

5 个答案:

答案 0 :(得分:3)

是。首先,如果没有某种验证,你永远不应该直接使用GET变量,永远

此外,您不应允许任意指定要包含的路径。

相反,你应该直接限制包含在特定路径中的包含(并检查指定的路径是否指向该目录中的文件),如果你绝对需要那么多的动态,或者你应该传递引用的标记您想要包含的内容(然后执行类似查找关联数组以查看给定标记引用的文件的内容)。

后者的一个例子是这样的:

$allowed_pages = array(
  "page1" => "pages/page1.php",
  "page2" => "pages/page2.php",
  "foobar" => "pages/page7.php",
  "stuff" => "pages/blarg.php"
);

$page = $_GET['page'];
if(array_key_exists($allowed_pages, $page)) {
  include($allowed_pages[$page]);
}

(在这种情况下,只允许指定密钥的事实既可以作为验证,也可以作为可能包含的内容的限制。)

答案 1 :(得分:1)

这是风险,因为在$_GET["page"]中可以是除了之外的路径 - 例如../../settings.php中的其他内容。

应该像:

$allowedPages = array('news', 'contact', ...);
if ( in_array($_GET["page"], $allowedPages) ) {
    include "pages/".$_GET["page"].".php";
} else {
    throw new Exception('Page is not valid !');
}

好的方法是检查文件是否存在。

答案 2 :(得分:1)

您实际上是在让他们能够执行系统中存在的任何PHP。这是一个非常大的未知数。

从根本上说这是有风险的,因为即使现在没有“危险”代码指向,也可能会在将来出现。

答案 3 :(得分:1)

除了有白名单外,你还可以做这样的事情

$include = $_GET['page'];

if ( ! preg_match('/^[a-z-_]+$/i', $include)) {
    throw new Exception('Access denied');
}

答案 4 :(得分:1)

  

包括“pages /".$_ GET [”page“]。”。php“;

您对前缀进行了硬编码这一事实可以防止以下攻击:

?页= HTTP%3A%2F%2Fwww.blackhat.com%2Fbad.code%3F

但是因为$ _GET ['page']可能包含'..',所以有人可以从你的系统强制包含任何文件和php扩展名。您是否确信这绝不会导致安全妥协?

使用其他人建议的白名单更加安全,并且还删除了为路径添加前缀以避免远程包含漏洞的要求。

下进行。