使用 $_FILES 数组在 PHP 中遍历目录?

信息安全 php 上传文件 目录遍历
2021-09-09 08:19:32

我正在开发一个处理文件上传的 php 应用程序。我正在尝试在文件名中注入路径横向有效负载,例如/../../../../etc/.

问题是易受攻击的代码行通过$_FILES["name"]数组使用文件名。这个内置的 php 数组对所有易受攻击的特殊字符进行自动清理。

我想知道这是否是一种足够的保护,或者我们是否需要添加一些其他的消毒措施?有没有办法绕过 php 清理?

2个回答

...易受攻击的代码行...

以何种方式易受攻击?

  • 如果最终用户可以覆盖 /etc 中的文件,那么您有一个严重的权限问题

  • 如果用户可以说服您的应用程序他已上传(例如)/etc/shadow,但由于权限问题导致写入失败,然后能够检索/etc/shadow,除了您遇到的权限问题应用程序代码中的事务管理/错误处理的一个大问题

简短的版本是 $_FILES[]["name"] 参数由用户提供/控制。如果您使用数据来确定服务器上内容的文件名/位置,目录遍历只是您将遇到的问题之一。还有更多惊喜等着你

您可能需要保留 $_FILES[]["name"] 数据以进行索引,但在您的服务器上选择一个新名称/位置,最好与明确将其标识为上传内容的 mimetype 相关联。

请注意,如果您确实遵循此建议,并且需要保留名称数据,请记住,您可能会增加攻击面,具体取决于您存储用户提供的名称和您选择的名称之间的映射的方式(例如,数据可能变为SQL 注入的向量)。

根据我的经验,$_FILES["uerrfile"]["name"]已经只包含一个文件名部分,路径被剥离了。

但是,PHP 手册建议无论如何都要使用该basename()函数,所以我无权告诉你。

附带说明一下,我不建议使用原始文件名,因为它们处理起来非常不方便,因为它们可能会重复,或者包含特殊字符,或者太长而被截断等。

因此,由系统分配的新名称将更有用。我个人养成了md5()以文件内容命名文件的习惯,或者您可以使用任何其他方法,例如uniqid().