【问题标题】:How can I protect a PHP image upload script from exploits?如何保护 PHP 图片上传脚本免受攻击?
【发布时间】:2012-09-07 13:18:49
【问题描述】:

我已经创建了(使用a script 和一些来自 Stack 的帮助和一些来自朋友的帮助;我对 PHP 知之甚少)一个简单的页面,供当地非营利出版物使用,人们可以在其中上传照片。

我不擅长安全(出于无知,而不是故意疏忽),但我已采取以下步骤来保护此页面:

• PHP 脚本设置为仅接受 .jpg、.png 和 .tif 文件进行上传;
• 保存表单内容的子文件夹权限设置为700,保存上传照片的子文件夹权限设置为700;
• 根据文档,我的主机具有以下配置,以确保只有 .php 文件作为 .php 运行:

<FilesMatch \.php$>
    SetHandler php52-fcgi
</FilesMatch>

• 我已将 .htaccess 文件放在相关(主要和保存的内容)文件夹中:

RemoveHandler .php
RemoveHandler .inc
RemoveHandler .pl
RemoveHandler .cgi
RemoveHandler .py
RemoveHandler .fcgi

然而,一夜之间,有人找到了这个测试页面,并提交了一个看似完美无害的测试消息和小 .jpg。这是一个私人测试页面,其 URL 不直观,只有我和其他三个人知道;其他人都没有发送此测试。

这显然让我担心会发生一些奇怪的事情,而且我担心我对安全性的了解不够,无法确保此页面的安全。

我有什么明显的遗漏吗?

【问题讨论】:

  • 用户提供的文件名($_FILES['upload']['name'])不可信,很容易更改。不要检查这些扩展。如果检查 getimagesize() 是否返回有效结果,请检查 mime 类型。如果可能,生成您自己的文件名。

标签: php security


【解决方案1】:

在处理上传时,您应该记住,您可以在 $_FILES 数组中找到的所有数据都可能是伪造的。它通过 HTTP 传输,因此很容易将 image/jpg mime 提供给可执行文件,例如。

1- 检查真实的 mime

PHP 带有一些功能来检查文件的真实 mime。为此,您应该使用fileinfo

$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
$filename = "/var/tmp/afile.jpg";
echo $finfo->file($filename);

2- 检查图像的属性

你显然只想上传图片,所以接收到的文件必须有一个宽度和一个高度:

使用getImageSize() 获取有关图像的所有必需信息。如果它返回 false ,则该文件可能不是图像,您可以将其删除。 getImageSize 也可以给你一个 mime 类型,但我不知道它是否可以信任。

2.5- 重新处理图像

根据 user628405 的建议,使用 GD 重新处理图像可能是更安全的做法。

$img = imagecreatefrompng('vulnerable.png'); 
imagepng($img, 'safe.png');

显然它必须根据图像类型进行调整。查看 php 文档中的所有 imagecreatefrom*。

3- 上传文件夹 除了你已经做过的事情:

确保您的上传文件夹无法通过网络访问。验证上传的文件,然后根据需要将其移动到其他文件夹并重命名文件。 它将防止黑客执行恶意文件(如果无法通过url访问则无法执行)。

延伸阅读:https://www.owasp.org/index.php/Unrestricted_File_Upload

【讨论】:

  • 有一次我遇到了这样的情况,有人将&lt;?php phpinfo();?&gt; 插入二进制数据的PNG 文件上传到我的网络服务器。此代码不可执行,但仍可通过 include() 函数访问。不幸的是,getimagesize() 返回了非假值。我通过$img = imagecreatefrompng('vulnerable.png'); imagepng($img, 'safe.png');重新保存所有上传的图像来处理这种情况@
  • 我对这一切还很陌生,不怕自己做作业,但有几个问题:首先,我会添加 fileinfo 和 getImageSize 命令,以及文件-重命名位,在脚本的“案例'文件'”部分内?
  • 必须尽快对$_FILES['my_files']['tmp_name']变量进行所有检查;如果一切顺利,您就可以移动文件、重命名它,然后对它做任何您需要做的事情。
【解决方案2】:

不要依赖来自客户端的任何数据,包括内容类型!

不要将上传的文件保存在 Web 根目录中。上传的文件应该只能通过您的脚本访问,以便更好地控制。

请勿使用原始文件名和扩展名保存上传的文件!将此数据存储在数据库中以供以后检索。

【讨论】:

    【解决方案3】:

    您可以检查文件的 MIME 类型,但不用担心,只要您的 php 处理程序只能执行 .php 文件并且您要注意不在脚本中保存上传的 .php 文件,您就可以不暴露任何安全漏洞。

    这当然适用于 .php 文件以及安装在您服务器上的任何其他服务器端脚本语言。

    一个更好的主意是保留你接受的扩展的白色以保存在你的文件系统上。

    【讨论】:

    • 这与文件上传没有直接关系,但您可以上传带有恶意php代码的图像作为注释。如果网站上存在 LFI 漏洞,您可能会包含您的图像并执行恶意代码。
    【解决方案4】:

    我会忽略传入文件的 MIME 类型和文件扩展名。这些是可以伪造的。

    如果您要走这条路,请将这些文件存储在一个目录中。

    确保该目录仅用于图像(音乐),然后通过查看文件格式获取脚本以在其上放置正确的扩展名。

    还要确保该目录不能执行 PHP(或其他任何东西)。

    这将确保您的安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-02
      • 2020-05-12
      • 2016-10-28
      • 2017-04-07
      • 2015-12-08
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      相关资源
      最近更新 更多