PHP图像上传安全方法

时间:2011-09-06 08:37:00

标签: php security file-upload

我开发了一个PHP脚本来替换当前的脚本,这将有很多市场/国家的曝光。 其他人之间的这个脚本提供了照片上传功能。

经过大量关于这个问题的阅读后,我采用了下面描述的方法。 我非常感谢您对其安全性的评论。

  1. 照片上传到网络根目录外的私人777文件夹中。
  2. 检查列出白名单的扩展名(仅允许jpgs,gifs,png),其他所有内容都将被删除。
  3. 使用getimagesize检查最小 - 最大尺寸和照片有效性。
  4. 检查mimetype和文件扩展名匹配。
  5. 将上传的照片调整为标准尺寸(使用imagecopyresampled)。
  6. 将创建的文件保存为jpg。
  7. 删除原始文件。
  8. 使用新的(非随机名称)即img51244.jpg保存照片。
  9. 根据不可预测的算法将新照片移动到公用文件夹的变量子目录(777权限)。即,img10000.jpg将存储在photos/a/f/0/img10000.jpg,而img10001.jpg将存储在photos/0/9/3/img10001.jpg。这是出于其他原因(使用子域进行静态内容服务或使用CDN)。
  10. 该脚本将在Linux专用服务器上运行。

3 个答案:

答案 0 :(得分:4)

  1. 根据定义,chmod 0777的目录对于登录到您服务器的其他用户是公开的,而不是私有的。正确的权限将是700并由apache(或您的网络服务器运行的任何用户)拥有。我不知道为什么你不会在这里使用php的默认临时目录,因为它也往往不在web根目录之外。
  2. 白名单是个好主意。注意正确实施。例如,正则表达式/.png/实际上与apng.php匹配。
  3. 这一步是个好主意。它基本上检查文件魔法。
  4. 不是绝对必要的。在前两个步骤中,我们确定扩展名和文件格式是正确的。如果您需要客户端指定正确的MIME类型,则还应检查给定的MIME类型和上面确定的MIME类型是否相同。
  5. 步骤5到8与安全无关。

    第9步:我假设您的网站允许所有人查看每张照片。如果不是这种情况,您应该有一个URL方案,其中包含更长的URL(例如,图像的hashsum)。

答案 1 :(得分:3)

您还应该检查上传的文件大小,因为getimagesize有时会超出可用的RAM内存。假设您的脚本可能在任何时候崩溃(例如当电量下降时)也是很好的,因此您应该实施一些清理程序来删除不需要的文件。

答案 2 :(得分:-1)

这是一个非常完整的方法,但我没有看到任何代码执行预防机制。

您应该确保永远不会包含图像内容(使用include或require调用)或通过eval()执行。

否则,可以执行文件末尾包含的php代码。

您还可以尝试检测图像内容中的PHP代码(使用file_get_contents,然后使用正则表达式搜索“<?php”)但我找不到100%安全的方法来消除可疑代码而不会破坏一些(有效的)图像。