为通过现有文件夹结构生成用于呼叫页面的白名单是否不安全?

问题描述 投票:0回答:1

...而不是在PHP数组中手动​​维护它们?

在Web应用程序中,我通过URL参数控制页面的调用,例如“页”。作为一项安全功能,我创建了一个白名单作为数组,如下所示:

$validPageValues = ['foo', 'bar', 'baz'];

在加载页面之前,应用程序检查page参数的值是否对应于白名单中的条目。在上面的示例中,有效值将是“ foo”,“ bar”和“ baz”,而不是“ evilfolder”]

每个页面都有其自己的文件夹,每个页面都有一个模板。

templates/
    foo
    bar
    baz

我现在正在考虑根据“模板”中的现有文件夹自动填充白名单。但是,我不确定这是否会导致安全漏洞。如果例如有人设法在此服务器上创建一个文件夹并将恶意代码存储在其中。

[进行比较:您可以说设法创建一个文件夹并放置恶意代码的人也可以将白名单放入php文件并进行调整。但是我认为它们之间是有区别的。创建带有恶意内容的文件夹肯定可以通过多种方式进行,而无需访问整个文件系统。在“受保护的”系统中修改PHP文件肯定更困难。

另一个类似的考虑因素:根据page参数动态加载PHP类或方法。每个页面都有一个类,我也正在考虑通过该参数自动加载并使用自动加载器实例化的PHP类或接口类的方法。对于我来说,根据用户请求加载类甚至更成问题。我并不是很想这样做,但是我想知道是否有这种可能性,值得考虑。

我在这里读到类似的内容-Dynamic php class generation based on url parameters最后的解决方案与我要寻找的解决方案不同。

预先感谢您的帮助和答复。

php security
1个回答
0
投票

我真的很喜欢您的问题,并认为它很有趣,因此我将尝试回答它。如果您觉得我应该在答案的某些方面提供更多详细信息,请随时发表评论,我将尽力扩大答案。

在评论中详细说明后,您的问题似乎可以归结为:

根据用户输入动态检查目录是否存在是不安全的?

要回答这个问题,我们必须研究安全性的多个方面,但首先要问自己,“安全”的真正含义是什么。

什么是安全性?

我想在这里指出,安全始终是“为破坏系统所做的工作”与“这样做可能对系统造成的损害”之间的比率。也就是说,如果您付出了很多努力(出于争论的缘故,可以说是无限努力),则您很可能迟早会破坏每个系统(即,花费更多或更少的精力)。

已经说过,我们应该将本主题的范围缩小到PHP。您可能知道,也可能不知道,PHP主要是用C和C ++编写的,在PHP自身可能存在的问题之上,它们都有各自的缺陷(这是因为PHP的作者确实错过了一些东西) 。我仅提及这一点是为了指出,要考虑多层安全性,因此,对于100%的答案,绝不应采用“这种安全”的答案。

通过用户输入动态检查文件夹是否“安全”?

取决于!

进入细节之前,请注意是否:

  1. 您可以通过用户输入动态建立白名单,或
  2. 您动态检查是否有一个来自用户输入名称的文件夹

从安全角度来看,可以认为是同一件事,只有漏洞的发生时间会有所不同。

现在,进入细节,正如我已经说过的:这取决于!有很多可能的实现方式确实会打开每个邪恶输入的大门,例如运行系统命令来检查文件夹是否存在,这是一个示例:

$input = $_GET['folder']; // let's say this is called like /?folder=foo
exec("test -d " . $input, $output, $return);
$doesFolderExist = ($return == 0); // variable would be true if folder exists

这是实现文件夹是否存在的一种方法,但是它是一个故意的愚蠢方法,用于演示一个文件夹可能会出错的地方。为什么这么傻?它对Command Injection广泛开放。例如,攻击者可以像/?folder=foo;rm -rf /这样调用URL,并且可能会删除服务器的整个磁盘。

返回合理的解决方案

在我对上面没有什么是完全安全的问题进行了一些讨论之后,肯定有一些方法-至少从我的角度来看-可以被认为足够安全,可以被用户输入信任。一种选择是使用glob()并检查文件夹是否存在,但是我认为这甚至不必要地复杂。

对于您的特定用例,我认为简单的glob()检查就足够了,并且不能打开邪恶用户输入的大门,让我们从上面重新查看示例:

file_exists()

[您可以看到我添加了file_exists()常量以检查相对于当前PHP文件的文件夹是否存在,您可能必须根据使用情况对其进行调整。

但是有一个陷阱,所以请不要按原样使用此解决方案,请继续阅读!

精巧的攻击者可能会发现您正在使用相对路径,并尝试在该文件系统中级联地探查一个奇怪的参数,以检查是否存在某些问题。例如,攻击者可能会调用$input = $_GET['folder']; // again, imagine this is called like /?folder=foo $doesFolderExist = file_exists(__DIR__ . $input); // variable would be true if folder exists 之类的URL,这可能使他了解该系统中是否存在名为“ admin”的用户。

可能的用例很多,这就是为什么使用用户输入进行此类文件/目录检查时应始终限于非常特定的范围。例如,您可以通过替换语法来确保无法向上移动文件夹,因此最终的解决方案如下所示:

__DIR__

这样,攻击者将“仅”知道在您的PHP文件所在的目录中是否存在一个名为/?folder=../../home/admin的子文件夹,但实际上并未发现是否存在名称为“ foo”的系统用户。当然,根据您的预期结构,始终可以进行更多消毒。例如,如果仅允许一个级别的子文件夹,则可以替换(与示例中的方式相同)用户输入中的所有斜杠。

简而言之

我希望我能指出,安全永远不会是绝对的,但是只要您采取必要的措施,您在安全方面就几乎可以做到,这里是您(几乎)应始终遵循的一些基本规则:

  1. 所有输入都是邪恶的,将其视为邪恶
  2. 尝试思考打破自己的解决方案的方法
  3. 如果有疑问,请考虑最坏的情况

希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.