Слабым местом вашей текущей реализации является то, что…
- регулярное выражение просто проверяет начало строки, так что «
images/../../secret
» пройдет, а
- без дальнейшей проверки, «
index
» также будет допустимым значением и вызовет рекурсию.
Чтобы сделать вашу реализацию безопасной, рекомендуется помещать все, что предполагается включить, в отдельный каталог (например, «includes
» и «templates
»). Исходя из этого, вы просто должны убедиться, что нет выхода из этого каталога.
if (preg_match('/^[a-z0-9]+$/', $_GET['page'])) {
$page = realpath('includes/'.$_GET['page'].'.php');
$tpl = realpath('templates/'.$_GET['page'].'.html');
if ($page && $tpl) {
include $page;
include $tpl;
} else {
// log error!
}
} else {
// log error!
}
Примечание: realpath
возвращает абсолютный путь к указанному относительному пути, если файл существует, и false
в противном случае. Так что file_exists
не нужно.