4

例如,一个简单的 MVC 类型系统:

/api/class/method使用 重写为 PHP 变量.htaccess/nginx.conf,然后执行以下操作:

<?php

// Set up class + method variables
$className = some_class_filter($_GET['class']);
$method = some_method_filter($_GET['method']);

// Check if class exists and execute
if(file_exists(BASE . "/controllers/" . $className . ".class.php")) {
    require BASE . "/controllers/" . $className . ".class.php";
    $$className = new $className();

    // Execute the method
    $$className->$method();
} else {
    // Spit out some error based on the problem
}

?>

这是非常糟糕的做法吗?如果这是不好的做法,有人可以解释一下为什么吗?如果是这样,有没有更好的方法来做我正在做的事情?

编辑本质上,我使用变量变量的原因是为了简化核心系统的扩展——即——添加一个新的控制器既好又简单。我绝对理解允许在没有某种过滤器的情况下实例化基本上任何函数或类的安全风险。

'some_filter_here' 可能是允许的控制器列表 - 此处有些人提到的白名单。

4

3 回答 3

6

是的,这是相当糟糕的做法。您是否需要该实例的变量变量?换句话说,您是否需要在给定请求中实例化多个类和方法?您的 URI 结构表明不是。如果没有,您可以使用:

$object = new $className();
$object->$method();

否则,您可能想要这样做:

$objects = array();
$objects[$className] = new $className();
$objects[$className]->$method();

这避免了变量变量污染范围,这些变量更难跟踪。

就给定目录中的类的存在性检查而言,这应该是一个足够的白名单(假设攻击者无法写入该目录)。

编辑:作为进一步检查,您可能需要考虑method_exists在调用方法之前检查对象。

于 2012-01-03T17:17:11.607 回答
1

由于您正在编写“some_class_filter”和“some_method_filter”代码,我会说没关系。我看到你还有一个错误或默认处理程序,所以最后,我会说没关系。

我相信许多 MVC 框架无论如何都以类似的方式运行。

于 2012-01-03T17:14:26.200 回答
1

它们不是可取的,但可以按你的方式使用它们。

不过,有几点建议:您的代码确实存在漏洞,攻击者可以使用$_GET诸如?class=../base. 如果该文件存在,您的file_exists()调用将返回true,您的应用程序将尝试包含它并将其实例化为一个类。

安全的方案是将这些参数列入白名单,仅是字母、数字和下划线(如果您用下划线分隔单词,即 ie .php)。

另外,我更喜欢使用call_user_funcand的语法call_user_func_array。在您的代码中使用这些函数将如下所示:

<?php
$class_name = $_GET['class'];
$method_name = $_GET['method'];

$parameters = $_GET;
unset($parameters['class'], $parameters['method']); // grabs any other $_GET parameters

if (file_exists(BASE.'/controllers/'.$class_name.'.class.php')) {
    require BASE.'/controllers/'.$class_name.'.class.php';
    $controller = new $class_name();
    $response = call_user_func_array(array($controller, $action_name), $parameters);
}
else {
    header('HTTP/1.1 404 Not Found');
    // ...and display an error message
}
于 2012-01-03T17:28:51.000 回答