从 URL 获取参数安全地实例化 PHP class?

Securely instantiate PHP class from URL get parameter?

我写了一个小代码片段,应该根据 get 参数实例化 php class。

(根据@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");
  }

在这个类似的问题中被警告做这样的事情: Call PHP function from url?

在其他问题中,人们有时会在使用不安全代码时收到警告 - 现在我 尝试 删除 一些 安全问题(在我的代码中) 基于这些警告,使用 filter_input 并且只需要存在的文件。也许这还不够或程序不正确?

我是否也应该将现有页面和可能的参数列入白名单,或者采取其他措施来避免安全问题,或者这是否没有必要?

像这样:

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

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

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

}

如果我的问题的背景不清楚从你的角度请描述问题以帮助我指定它。

谢谢!

I tried to remove security issues (in my code) based on these warnings by using filter_input

抱歉 - 您没有消除安全问题,此代码仍然容易受到目录遍历的攻击。 filter_input() 函数是恕我直言,一个 非常 不合适的函数。你永远不应该改变输入的表示,但你应该验证它。但是 filter_input() 需要被告知 如何 你想验证它。而且它没有部分文件名的选项。

Should I whitelist existing pages

如果您修复了目录遍历问题,那么您已经将可以是 运行 的脚本列入白名单 - 将只能 运行 指定目录中的脚本。

考虑:

$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;

使用正则表达式 remove/retain 任意字符不是一个优雅的解决方案。