基本上,我已经在网站上工作了好几个月了,我即将打开它。在开放之前,我正在讨论潜在的安全问题,我已经在网上进行了一些研究,以找出php中的cummon安全问题,我已经知道如何修复它们中的大部分,尽管我确实遇到了问题其中之一:我想避免使用include($_GET['page'])
,我已经做了一些研究,但没有找到任何真正方便使用的东西,虽然有什么方法可以“保护”我的代码原样吗?登记/>
以下是我编写的用于防止安全问题的内容:
if (!isset($_GET['page']))
{
echo redirect_tempo(500, 'index.php?page=home');
}
elseif ($_GET['page']=="index")
{
echo redirect_tempo(500, 'index.php?page=home');
}
elseif (file_exists($_GET['page'].".php"))
{
require $_GET['page'].'.php';
}
else
{
echo redirect_tempo(500, 'index.php?page=404');
}
请注意,redirect_temp()
基本上只是header()
。
这是否足够,我可以改进它,还是只需要完全改变它?
答案 0 :(得分:3)
这部分很危险:
elseif (file_exists($_GET['page'].".php"))
我可以给路径"../../../../etc/passwd"
(我知道,这有点旧,但它可能是任何东西)并且它会读取文件(给予足够的权限)。
一个简单的解决方法可能是:
elseif (file_exists(basename($_GET['page']) . ".php"))
不要忘记对实际require
:
require basename($_GET['page']) . '.php';
您还可以进一步申请basename()
,这样您就不必再申请该功能
另请参阅:basename
答案 1 :(得分:0)
做你的方法没什么不对。只需添加一些基本验证,就知道恶意用户不会尝试访问其他路径。
我建议验证字符串中没有斜杠和点(因为Windows中的../或/或\等路径)。甚至可能在最后对.PHP进行硬编码以防止访问其他文件类型。
if (strstr($_GET['page'], ".") || strstr($_GET['page'], "/") || strstr($_GET['page'], "\\")
{
echo "error";
exit;
}
include($_GET['page'] .".php");
答案 2 :(得分:0)
继续我的评论,我会做这样的事情。
switch($_GET['page']) {
case 'index' :
redirect_tempo(500, 'index.php?page=home');
break;
........
default :
die('NO!');
break;
}
然而,这不是解决这个问题的最好方法。
答案 3 :(得分:0)
您的代码看起来不错。但是如果你在使用前验证你的GET值会更好。您可以检查它是仅数字还是仅限字母或字母数字。它可以是单个单词或多个单词。根据您的要求检查。
答案 4 :(得分:0)
这将包括所有允许的页面,因此$ _GET ['page'] ==搜索将包含search.php,但$ _GET ['page'] ==某些内容将包含home.php:]
$allowed_pages = array('home', 'search', 'signup', 'signin', 'loggedin');
if(in_array($_GET["page"], $allowed_pages)) {
$page = $_GET["page"];
} else {
$page = "home";
}
$page = str_replace('/', '', $page);
if(file_exists("page_includes/$page.php")) {
include("page_includes/$page.php");
} else {
include("page_includes/home.php");
}
答案 5 :(得分:0)
我使用白名单:
$all_pages = array(
'index' => 'index.php',
'about' => 'misc/about.php',
'404' => '404.php',
...
);
function reverse($filename) {
/* maps filenames to page names */
return preg_replace('#/pages/(.*).php#', '$1', $filename);
}
/* add all php files in pages/ directory to $all_pages */
foreach (glob("pages/*.php") as $filename) {
$all_pages[reverse($filename)] = $filename;
}
/* for debugging: make sure this only prints stuffs you want to include */
/* var_dump($all_pages); */
/* the actual check is simple */
$page_name = isset($_GET['page']) ? $_GET['page'] : "index";
$include_name = isset($all_pages[$page_name]) ? $all_pages[$page_name] : "404";
require $include_name;
答案 6 :(得分:0)
很多这些答案都忘记了null-byte attacks。追加" .php"防止像../../../../../etc/passwd这样的东西在许多部署中都不起作用。此问题仅在PHP 5.3.4中正确修复。