1

在我之前的动态调用函数中,从变量Sven 传递参数指出我的代码容易受到本地文件包含的攻击。我做了一些修改以防止 LFI。够了还是我应该担心?

if ($_SERVER['HTTP_X_REQUESTED_WITH'] !== "XMLHttpRequest") 
    {
        echo "Error"; 
        exit();

    }
    $req = explode("_",$_POST['req']);
    /*
      User input should always be escaped 
      using preg_quote before being used in a regexp pattern.
      Thanks bwoebi 
    */
    $className = preg_quote($req[0]) . "Controller" ;
    $methodName = $req[1];
    $args= isset($_POST["data"]) ? $_POST['data'] : array();


    $file = "application/controllers/" . $className . ".php" ;

    if (!file_exists($file) || preg_match("/^[a-z]$/", strtolower($className)))
        exit();

    require_once $file;

    $controller = new $className;
    $result = call_user_func_array(array($controller, $methodName),$args );

    echo json_encode($result);

另一个问题可能是用户可以从文件夹中调用任何控制器文件的公共方法。但据我所知,更多框架在其路由中使用 domain.xy/controller/method/par 模式,这具有相同的风险。(虽然在我的控制器中我使用尽可能多的服务器端验证)

我正在考虑将一些身份验证放入 ajax 处理程序/路由器文件中。

// PSEUDO CODE

$user = new User();
// maybe bad practice to store the id session after authentication. Any comment on this?
$userGroup =$user->getUserGroupById($_SESSION["user"]);

$security = new Security();
$whiteList = $security->getWhiteList($userGroup);
//$whiteList is an array with the list of controllers the user may access 
if (!in_array(className, $whiteList ))
 exit();

欢迎任何意见,最佳实践示例!

4

2 回答 2

1

它现在应该是安全的,因为您不允许在正则表达式中包含恶意点和 NUL 字节。

但这仍然不是一个好习惯。你真的应该将它与你的白名单相匹配。正如您所说,它是安全的,并且只允许用户选择您允许用户选择的控制器。

tl; dr:使用您在伪代码中编写的内容。

于 2013-07-25T21:07:29.077 回答
0

老实说,您的代码看起来很乱。

  • 没有在正则表达式模式中使用$className,那么您为什么要尝试使用 来逃避它preg_quote()

  • 为什么要先检查类文件是否存在,然后才检查类名是否允许?这对我来说似乎倒退了。(在这种情况下,它不应该造成任何实际伤害,但是在将输入用于任何事情之前进行输入验证是一种很好的做法。)

  • 无论如何,您的无效类名检查不是向后吗?您的

    preg_match("/^[a-z]$/", strtolower($className))
    

    $className仅当仅包含字母时才会返回 true 。(此外,使用strtolower()是一种非常低效的不区分大小写匹配的方法。)不应该是这样吗?

    !preg_match('/^[a-z]$/i', $className)
    

    甚至

    preg_match('/[^a-z]/i', $className)
    

    反而?

如果您修复了所有这些问题,您的代码可能没问题(假设您在这样做时没有引入任何新错误)。

例如,您可以通过创建一个名为的文件来测试它,application/BogusController.php并查看是否可以通过../Bogus作为类名传递来包含它。尝试考虑其他可能的变化,并测试它们。

在任何情况下,就像 bwoebi 笔记一样,您的伪代码使用了更安全的方法,并且应该更难出错。我也建议你去。

于 2013-07-26T00:38:48.527 回答