以下包含声明是否存在安全风险?
include "pages/".$_GET["page"].".php";
如果是:
- 为什么?
- 什么是更安全的方法?
答案 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扩展名。您是否确信这绝不会导致安全妥协?
使用其他人建议的白名单更加安全,并且还删除了为路径添加前缀以避免远程包含漏洞的要求。
下进行。