我真的很担心人们能够上传恶意的php文件,安全风险很大!
冰山一角!
我还需要注意人们更改 php 文件的扩展名以试图绕过此安全功能。
通常更改扩展名将阻止 PHP 将这些文件解释为脚本。但这不是唯一的问题。除了 '...php' 之外,还有更多的东西会损坏服务器端;'.htaccess' 和设置了 X 位的文件是显而易见的,但绝不是您需要担心的全部。即使忽略服务器端的东西,也存在一个巨大的客户端问题。
例如,如果有人可以上传一个 '.html' 文件,他们可以在其中包含一个 <script> 标签来劫持第三方用户的会话,并删除他们所有上传的文件或更改他们的密码或其他东西。这是典型的跨站点脚本 (XSS) 攻击。
另外,由于某些浏览器(主要是 IE)的“内容嗅探”行为,以“.gif”形式上传的文件实际上可能包含诸如此类的恶意 HTML。如果 IE 在文件开头附近看到类似(但不限于)“<html>”之类的信息,它可以忽略提供的“Content-Type”并显示为 HTML,从而导致 XSS。
此外,可以制作一个文件,该文件既是您的图像解析器将接受的有效图像,又包含嵌入的 HTML。根据用户浏览器的确切版本和图像文件的确切格式(尤其是 JPEG 具有一组非常可变的可能标题格式),可能会出现各种结果。IE8 中有一些缓解措施,但现在没有用,你不得不想知道为什么他们不能简单地停止进行内容嗅探,你们这些白痴 MS,而不是给我们负担本应具有的 HTTP 标头的不合格的非标准扩展刚开始工作。
我又陷入了咆哮。我会停下来。安全地提供用户提供的图像的策略:
1:永远不要使用取自用户输入的文件名将文件存储在服务器的文件系统上。这可以防止错误和攻击:不同的文件系统对于文件名中允许哪些字符有不同的规则,而且“清理”文件名比您想象的要困难得多。
即使你使用了一些非常严格的东西,比如“只有 ASCII 字母”,你仍然需要担心太长、太短和保留的名称:尝试将一个像“com.txt”这样无害的名称保存在Windows 服务器并观察您的应用程序出现故障。认为您知道您的应用程序可能在其上运行的每个文件系统的路径名的所有奇怪缺点吗?自信的?
相反,将文件详细信息(例如名称和媒体类型)存储在数据库中,并使用主键作为文件存储中的名称(例如“74293.dat”)。然后,您需要一种方法来为它们提供不同的明显文件名,例如将文件吐出的下载器脚本、执行 Web 服务器内部重定向的下载器脚本或 URL 重写。
2:使用 ZipArchive 时要非常非常小心。extractTo 中存在相同类型的遍历漏洞,这些漏洞影响了大多数基于路径的 ZIP 提取器。此外,您还可以接受ZIP 炸弹的攻击。最好通过逐步检查存档中的每个文件条目(例如,使用zip_read/zip_entry_*)并检查其详细信息,然后手动将其流解压缩到具有已知良好名称和模式标志的文件,从而避免任何错误文件名的危险,您在没有存档帮助的情况下生成。忽略 ZIP 中的文件夹路径。
3:如果您可以加载图像文件并再次将其保存回来,特别是如果您在两者之间以某种方式处理它(例如调整大小/缩略图或添加水印),您可以合理地确定结果将是干净的。从理论上讲,可以制作一个针对特定图像压缩器的图像,这样当它被压缩时,结果也看起来像 HTML,但这对我来说似乎是一个非常困难的攻击。
4:如果您可以将所有图像作为下载提供(即在下载脚本中使用“Content-Disposition:附件”),那么您可能是安全的。但这对用户来说可能太不方便了。不过,这可以与 (3) 协同工作,提供更小的、已处理的内联图像,并且原始的高质量图像仅可作为下载使用。
5:如果您必须在线提供未更改的图像,您可以通过从不同的域提供它们来消除跨站点脚本风险。例如,对不受信任的图像使用“images.example.com”,对包含所有逻辑的主站点使用“www.example.com”。确保 cookie 仅限于正确的虚拟主机,并且设置了虚拟主机,以便它们除了正确的名称之外无法响应任何内容(另请参阅:DNS 重新绑定攻击)。这就是许多网络邮件服务所做的。
总之,用户提交的媒体内容是一个问题。
总结总结,AAAARRRRRRRGGGGHHH。
ETA 重新评论:
在顶部您提到“设置了 X 位的文件”,这是什么意思?
我不能说ZipArchive.extractTo()
因为我还没有测试过,但是许多提取器,当被要求从档案中转储文件时,将重新创建与每个文件关联的 [一些] Unix 文件模式标志(如果档案是在一个 Unix,所以实际上有模式标志)。如果缺少所有者读取权限,这可能会导致您出现权限问题。但是,如果您的服务器启用了 CGI,这也可能是一个安全问题:X 位可以允许将文件解释为脚本并传递给第一行 hashbang 中列出的任何脚本解释器。
我以为 .htaccess 必须在主根目录中,不是这样吗?
取决于 Apache 的设置方式,尤其是 AllowOverride 指令。通用主机在任何目录上允许覆盖是很常见的。
如果有人仍然上传像 ../var/www/wr_dir/evil.php 这样的文件会发生什么?
我希望领先的“..”会被丢弃,这就是遭受相同漏洞的其他工具所做的。
但是我仍然不相信extractTo()
恶意输入,有太多奇怪的小文件名/目录树的东西可能会出错 - 特别是如果你期望在 Windows 服务器上运行。zip_read()
使您可以更好地控制取消归档过程,从而减少攻击者。