我目前正在开发一个网站,我想使用PHP进行动态网站加载。
现在我想出了这个......
if (preg_match('/^[a-z0-9]+$/', isset($_GET['site']))) {
$general = realpath('includes/general/' . $_GET['site'] . '.php');
$laboratories = realpath('includes/laboratories/' . $_GET['site'] . '.php');
$validation = realpath('includes/validation/' . $_GET['site'] . '.php');
$training = realpath('includes/training/' . $_GET['site'] . '.php');
$reagents = realpath('includes/reagents/' . $_GET['site'] . '.php');
if ($general) {
include $general;
} else if ($laboratories) {
include $laboratories;
} else if ($validation) {
include $validation;
} else if ($training) {
include $training;
} else if ($reagents) {
include $reagents;
} else {
$default = realpath('includes/general/home.php');
include $default;
}
} else {
$default = realpath('includes/general/home.php');
include $default;
}
您如何看待这个?这样安全吗?
答案 0 :(得分:0)
对于$_GET['site']
可以携带的每个值,只包含一个文件,您可以将该映射存储在白名单中:
$include_path = '/path/to/includes';
$include_default = '/general/home.php';
$includes = [
'home' => 'general/home.php',
// ...
'lab-zero' => 'laboratories/lab-zero.php',
// ...
];
$include = $include_default;
if (isset($includes[$_GET['site']])) {
$include = $includes[$_GET['site']];
}
$path = $include_path . $include;
$real = realpath($path);
if ($real === $path && is_readable($real)) {
include $real;
}
然后只允许那些$_GET['site']
参数,这些参数有意义(那些已经制定了计划的参数,那些已在$includes
数组中配置的参数)。
此外,如果白名单包含错误,则不包含该文件(realpath
和is_readable
检查)。
正如您所看到的,$_GET['site']
的值已完全屏蔽了include path参数。这只能通过白名单来实现,这使得这种方法非常稳定。
最重要的是,这有效地保护了您的代码在检查中存在缺陷并且通过对文件系统进行白名单而导致危险的遍历攻击。
答案 1 :(得分:0)
我必须进行一些更改才能使您的代码正常工作。
<?php
$include_path = 'includes/';
$include_default = 'general/home.php';
$includes = [
'home' => 'general/home.php',
'laboratories' => 'laboratories/laboratories.php',
'validation' => 'validation/validation.php',
'training' => 'training/training.php',
'reagents' => 'reagents/reagents.php',
];
$include = $include_default;
if (isset($_GET['site'])) {
$include = $includes[$_GET['site']];
}
$path = $include_path . $include;
$real = realpath($path);
if (is_readable($real)) {
include $real;
}
?>
这是否仍然安全
if ($real === $path && is_readable($real)) {
因为它比较了两件不同的事情,所以不会工作。