2

我一直在研究如何安全地上传图片,并且很明显,实际提供图片是最有风险的地方,因为恶意 PHP 文件可能会危及服务器。

许多人建议使用图像处理脚本,例如 getimage.php?i=575748,它会在数据库 575748 中查找并实际返回 myphoto.jpg(用户不知道原始图像的位置)更安全。

任何人都可以指出我应该在脚本中实施什么样的事情的正确方向吗?我知道设置内容类型标头是必须的,但这足以阻止代码执行吗?

谢谢!

4

4 回答 4

0

将上传文件夹放在根文件夹之外(即,在 /www/ 或 /htdocs/ 或 /httpdocs/ 文件夹之外)是为了一件事。设置文件夹的权限,以便只有本地用户可以写入。

至于数据库的想法,你绝对可以继续做,结合上面提到的想法,应该会产生一个相当安全的图像上传服务。

唯一涉及的风险是当您没有在要上传到的文件夹上设置正确的权限时,这确实可能会危及服务器。

于 2012-09-17T17:29:45.643 回答
0

啊,我明白了。如果您不想让它们在文件系统中浮动,您也可以将图像存储在数据库中。无论您喜欢哪种方式。使用脚本而不是 Apache 来提供图像的问题是图像必须加载到内存中。因此,请为性能影响做好准备。

于 2012-09-17T17:30:34.490 回答
0

并且很明显,实际提供图像是大部分风险在于可能危及服务器的流氓 PHP 文件

仅当满足两个条件时才会发生这种情况:

  • 您允许上传非图像文件
  • 下载是通过直接链接完成的

挫败其中之一,危险就消失了。当然关闭两者更好。

数据库解决方案旨在破坏条件#2,但您也可以在上传图像时检查它是否确实是使用该getImageSize()功能的图像。或尝试使用imageCreateFromJPEG()或其他适当的功能加载图像。

如果加载的对象不是图像,则只显示“对不起,图像已损坏”。这既可以保护您的用户免于上传损坏的图像,也可以保护您免于有人上传流氓 PHP 文件(或者可能是受版权保护的视频或破解的可执行文件或......)。

更新:您还可以混淆已经存在的上传和下载工具:

假设当前您上传用户图像,为其分配唯一 ID,将其另存为,并作为 URL./images/UNIQUEID.jpg提供给用户。http://www.yoursite.com/images/UNIQUEID.jpg

  • 您应用 a.htaccess以便将访问./images/whatever重定向到./images/index.php?ID=whatever
  • 您创建一个index.php脚本,它接受“任何”、提取图像 ID 并输出图像。

所有旧的 URL 将继续工作,并且似乎直接加载图像,但它们实际上正在做的是调用一个 PHP 脚本来检查图像并将其作为字节流发送,而不进行解释。

您需要设置图像文件ETag的 ID、Last-Modified图像file_mtime()文件和Content-Length文件大小。此外,您可能需要检查传入的标头If-Modified-Since,并且If-None-Match:如果文件的日期对应于 IMS 或 IFN 值对应于 ID,则可以发送HTTP/304 Not Modified答案而不是图像,从而节省大量带宽。

于 2012-09-17T17:37:16.637 回答
0

解决您最初的安全问题,在图像存储之前对图像运行getimagesize()false - 如果您退出该功能,请将其丢弃。(如果有人知道防止不良“图像”通过的更好解决方案,我全神贯注!)

将图像存储在 Web 可访问目录之外的文件系统上。使用物理位置的密钥表是一个好主意。将IMAGETYPE_XXX值与它一起存储(它是由 返回的数组的第二个索引getimagesize())并打开它以使用imagejpeg()imagepng()等提供图像。当你这样做时不要忘记设置你的 Content-type 标题.

于 2012-09-17T17:39:26.270 回答