在我之前的帖子call function dynamically, passing arguments from variable中,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();
欢迎任何评论,最佳实践示例!
答案 0 :(得分:1)
现在应该是安全的,因为你不允许恶意点和NUL-Bytes包含在正则表达式中。
但这仍然不是好习惯。你真的应该与你的白名单相匹配。正如你所说的那样安全,只允许用户选择允许用户选择的控制器。
tl; dr:使用你在伪代码中写的内容。
答案 1 :(得分:0)
说实话,你的代码看起来很混乱。
你是不在正则表达式模式中使用$className
,那么为什么要尝试使用preg_quote()
转义呢?
为什么首先检查类文件是否存在,只有然后是否允许类名?这对我来说似乎是倒退。 (在这种情况下,它不应该造成任何实际伤害,但在使用任何的输入之前,最好先进行输入验证 。)
< / LI>无论如何,您的无效类名不是向后检查吗?您的
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笔记一样,你的伪代码使用了更安全的方法,应该更难弄错。我也建议你顺其自然。