在web应用程序中,我通过URL参数控制页面的调用,例如"页面";。作为一项安全功能,我创建了一个白名单作为一个数组,如下所示:
$validPageValues = ['foo', 'bar', 'baz'];
在加载页面之前,应用程序检查页面参数的值是否与白名单中的条目相对应。在上面的示例中,有效值将是">foo">bar";以及">baz";但不是">文件夹";
每个页面也有自己的文件夹,其中每个页面都有一个模板。
templates/
foo
bar
baz
我现在正在考虑基于"中的现有文件夹自动填充白名单;模板";。然而,我不确定这是否会导致安全漏洞。例如,如果某人设法在此服务器上创建一个文件夹并在其中存储恶意代码。
尝试比较:你可以说,那些设法创建文件夹并放置恶意代码的人也可以进入带有白名单的php文件并对其进行调整。但我认为他们之间有区别。在没有访问整个文件系统的情况下,通过多种方式创建包含恶意内容的文件夹当然是可能的。修改一个PHP文件在一个";"受保护";这个系统肯定更难。
另一个类似的考虑因素:基于页面参数动态加载PHP类或方法。每个页面也有一个类,我也在考虑通过这个参数自动加载PHP类或接口类的方法,并用自动加载器实例化。对我来说,基于用户请求加载一个类的问题更大。我真的不想这么做,但我想知道是否有这种可能性,是否值得考虑。
我在这里读到了类似的东西——基于url参数的动态php类生成,最终解决方案与我正在寻找的解决方案不同。
我真的很喜欢你的问题,认为它很有趣,所以我将尝试回答它。如果你觉得我应该在答案的某些方面提供更多细节,请随时发表评论,我会尽我所能扩大答案。
在你在评论中详细阐述后,你的问题似乎可以归结为:
根据用户输入动态检查目录是否存在是否不安全
要回答这个问题,我们必须考虑安全的多个方面,但首先要问问自己"安全"的真正含义。
什么是安全
我想在这里指出的是,安全始终是"为损害系统所做的工作"one_answers"这样做可能对系统造成的损害"之间的比率。也就是说,如果你付出了很多努力(为了论证起见,让我们说无限的努力),你很可能迟早会破坏每个系统(也就是说用更多或更少的努力)。
话虽如此,我们应该将本主题的范围缩小到PHP。正如你可能知道也可能不知道的那样,PHP主要是用C和C++编写的,除了PHP本身可能存在的问题之外,这两种语言都有自己的缺陷(这可能是因为PHP的作者确实遗漏了一些东西)。我提到这一点只是为了指出,有几个安全层面需要考虑,因此,"这样安全吗"之类的答案永远不应该被视为100%的答案。
通过用户输入动态检查文件夹是否"安全">
这取决于!
在详细介绍之前,请注意是否:
- 您可以根据用户输入或
- 您可以根据用户输入动态检查是否存在具有名称的文件夹 从安全的角度来看,
可以被认为是同一件事,只是缺陷的出现时间不同。
现在来看细节,正如我已经说过的:这取决于!有很多可能的实现会真正打开每一个邪恶输入的大门,比如运行系统命令来检查文件夹是否存在,这里有一个例子:
$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
这是实现文件夹是否存在的一种方法,但这是一种故意愚蠢的方法来证明人们在这方面可能会出错。为什么它很愚蠢?它对命令注入广泛开放。例如,攻击者可以调用类似/?folder=foo;rm -rf /
的URL,服务器可能会删除整个磁盘。
回到合理的解决方案
在我谈到了上面没有什么是完全安全的之后,肯定有一些方法——至少从我的角度来看——可以被认为足够安全,可以通过用户输入得到信任。一种选择是使用glob()
并检查文件夹是否在那里,但我认为这甚至是不必要的复杂。
对于您的特定用例,我认为一个简单的file_exists()
检查就足够了,并且不会打开恶意用户输入的大门,让我们重新访问上面的示例:
$input = $_GET['folder']; // again, imagine this is called like /?folder=foo
$doesFolderExist = file_exists(__DIR__ . $input); // variable would be true if folder exists
正如您所看到的,我添加了__DIR__
常量来检查文件夹相对于当前PHP文件的存在性,您可能需要根据您的用例进行调整。
然而,有一个陷阱,所以请不要按原样使用此解决方案,而是继续阅读
Nifty攻击者可能会发现你使用的是相对路径,并试图在文件系统中偷偷插入一个奇怪的参数,以检查是否存在某些东西。例如,攻击者可能会调用类似/?folder=../../home/admin
的URL,这可能会让他了解该系统中是否有名为"admin"的用户。
这方面可能有很多用例,这就是为什么这种使用用户输入的文件/目录检查应该始终限制在一个非常特定的范围内。例如,您可以通过替换掉语法来确保不可能向上遍历文件夹,因此最终的解决方案如下所示:
$input = $_GET['folder']; // attacker might call /?folder=../../user/foo
$input = str_replace('../', '', $input); // sanitize
$doesFolderExist = file_exists(__DIR__ . $input); // variable would be true if folder exists
这样,攻击者"只"知道在PHP文件所在的同一目录中是否有一个子文件夹user/foo
,但实际上并没有发现是否有一个名为"foo"的系统用户。当然,根据您的预期结构,更多的消毒总是可能的。例如,如果只允许一个级别的子文件夹,则可以替换掉用户输入中的所有斜杠(与示例中相同)。
简而言之
我希望我能指出,安全从来都不是绝对的,但只要你采取必要的措施,你就可以非常安全,以下是你应该(几乎)始终遵守的一些基本规则:
- 所有输入都是邪恶的,就这样对待它
- 试着想办法打破你自己的解决方案
- 如果有疑问,请考虑最坏的情况
希望这能有所帮助!