As for each value that $_GET['site']
can carry there is only one file to include, you can store that mapping in a whitelist:
$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;
}
Only those $_GET['site']
parameters are then allowed, that do make sense (those which have been made plans for, those that have been configured in $includes
array).
Additionally if the whitelist contains an error, that file is not included (realpath
and is_readable
checks).
As you can also see, the value of $_GET['site']
has been fully shielded from the include path parameter. This is only possible with a whitelist which makes this approach pretty stable.
Most importantly, this effectively protectes against traversal attacks which your code has been prone for by having a flaw in the checks and by white-listing against the file-system which is dangerous.