Безопасно создать экземпляр класса PHP из параметра получения URL-адреса?

Я написал небольшой фрагмент кода, который должен создать экземпляр класса php на основе параметра get.

(Код отредактирован на основе предложений @ sietse85 и @CBroe :)

  $this->pageVal = preg_replace('/[^A-Za-z]/', '', filter_input(INPUT_GET, 'page')) ? preg_replace('/[^A-Za-z]/', '', filter_input(INPUT_GET, 'page')) : "index";

  $file = $this->moduleDir . $this->pageVal . ".php";
  if (file_exists($file)) {
    require_once $file;
    $class = new $this->pageVal($this);
  } else {
    header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found", true, 404);
    $this->loadPage("404");
  }

В этом аналогичном вопросе предлагается сделать что-то вроде этого: Вызвать функцию PHP с URL-адреса?

В других вопросах люди иногда получают предупреждение, когда они используют небезопасный код - теперь я попытался удалить некоторые проблемы безопасности (в моем коде) на основе этих предупреждений, используя только filter_input и Requiere. файлы, которые существуют. Возможно, этого недостаточно или неправильная процедура?

Следует ли мне занести в белый список существующие страницы и возможные параметры или сделать что-то еще, чтобы избежать проблем с безопасностью, или в этом нет необходимости?

Нравится:

$existingPages = ["index", "profile", "login", "register"];

if(in_array(filter_input(INPUT_GET, 'page'), $existingPages)) {

  //GO ON WITH PROCESSING
  $this->pageVal = filter_input(...)

}

Если предыстория моего вопроса неясна с вашей точки зрения, опишите проблему, чтобы я мог ее уточнить.

Спасибо!


person Community    schedule 26.04.2018    source источник
comment
Поскольку похоже, что вы в настоящее время не приняли во внимание даже важные основы, такие как атака с обходом пути, я думаю, вам, вероятно, лучше пойти с белым списком ...   -  person CBroe    schedule 26.04.2018
comment
убедитесь, что вы удалили точки и косые черты из этого параметра get. На самом деле попробуйте разрешить только A-Za-z $this->pageVal = preg_replace('/[^A-Za-z]/', '', $this->pageVal);   -  person sietse85    schedule 26.04.2018
comment
Так что я бы использовал это ?: $this->pageVal = preg_replace('/[^A-Za-z]/', '', filter_input(INPUT_GET, 'page')) ? preg_replace('/[^A-Za-z]/', '', filter_input(INPUT_GET, 'page')) : "index"; Извините, это ужасно читать здесь - может быть, вставьте это в текстовый файл, чтобы прочитать? Я совместил это с тройной операцией.   -  person    schedule 26.04.2018
comment
Если вы спрашиваете о безопасности, это явный знак, что вам следует держаться подальше от этой темы. Не изобретайте велосипед, уже существует множество маршрутизаторов.   -  person emix    schedule 26.04.2018
comment
Спасибо за оценку моего вопроса и конструктивный отзыв.   -  person    schedule 27.04.2018


Ответы (1)


Я попытался удалить проблемы безопасности (в моем коде) на основе этих предупреждений с помощью filter_input

К сожалению, вы не устранили проблемы с безопасностью, этот код все еще уязвим для обхода каталогов. Функция filter_input() - ИМХО, это очень неподходящая функция. Вы никогда не должны изменять представление ввода, но вы должны его проверить. Однако filter_input () нужно сообщить, как вы хотите его проверить. И у него нет опции для частичного имени файла.

Следует ли занести существующие страницы в белый список

Если вы исправите проблему с обходом каталогов, значит, вы занесли в белый список скрипты, которые можно запускать - запускать скрипты можно будет только в указанном каталоге.

Рассмотреть возможность:

$this->pageVal = basename($_GET['file']);
$file = $this->moduleDir . $this->pageVal . ".php";
if (!is_readable($file)) {
    trigger_warning("User attempted to access non-existent code: " 
      . base64encode($_GET['page']), E_USER_WARNING);
    $this->pageVal = 'index';
    $file = $this->moduleDir . $this->pageVal . ".php";
}
require_once $file;

Использование регулярного выражения для удаления / сохранения произвольных символов не является изящным решением.

person symcbean    schedule 26.04.2018
comment
Спасибо! Это мне очень помогло. Копнув немного глубже в этой теме, я прочитал о basename () и realpath (). Как насчет объединения их с $this->pageVal = basename(realpath($_GET['page']));, чтобы удалить информацию о каталоге и получить полный путь? - person ; 26.04.2018
comment
Нет - потому что, если вы позволите пользователю указать каталог, вы снова получите обход каталога и потеряете свой белый список. - person symcbean; 26.04.2018
comment
Спасибо за помощь. Придется углубиться в эту тему. Ваш ответ показывает мне, что я, возможно, немного далек от приемлемого решения. - person ; 27.04.2018