繁体   English   中英

安全地提供图像

[英]Securely serving images

一位受人尊敬的同事坚持认为在我的服务器上存储图像是不安全的,特别是如果文件结构很容易猜测(因为我们有用户创建的图像库,命名方案很容易遵循)。

相反,他建议将图像存储在根目录之上,并使用fread或fputthrough为它们提供服务。

我无法弄清楚风险是什么,或者为什么在通过脚本提供服务时可以避免这些风险。
这样一个脚本的开销听起来很荒谬。

我知道在存储到服务器之前必须检查图像,为此我使用imagemagick做一个小的转换并保存到jpeg - 这应该摆脱任何渣滓,据我所知。

那么,对SO的伟大思想的问题:

  1. 使用易于遵循的路径在本地存储图像是否存在安全问题?
  2. 我使用IM安全检查图像的方法吗?
  3. 是否有理由使用PHP来提供图像?
  4. 使用PHP的开销真的很大吗?
  5. 使用CDN会在安全性方面产生影响(我不想)?
  6. 我错过了什么吗?

谢谢大家!

我怀疑你的朋友指的不是简单地提供图像,而是专门为用户提供的图像提供服务。 在提供用户提供的内容时存在许多安全问题。 在图像的情况下,有许多方法可以使用图像上载来使Web服务器执行代码。 一些较为知名的包括:

  • 一个“GIFAR”文件。 从本质上讲,这是一个GIF文件和一个连接的jar文件。 因为GIF的索引信息在开头,而jar文件的索引信息在最后,所以可以组合两种文件类型,结果是有效的GIF和有效的JAR。
  • 多个文件扩展名。 Web服务器支持多个文件扩展名,以实现国际化等功能。 例如,名为page.html.fr的文件可能会映射到页面的法语版本。 扩展名为image.php.jpg甚至image.php.123的文件可以作为PHP脚本执行,具体取决于服务器的配置。
  • 缓冲区溢出。 图像文件格式通常在开头包含一个标题,用于描述文件的大小和格式。 降低大小可能允许恶意用户制定缓冲区溢出攻击。

所有这些示例都能够将代码作为Web服务器执行。 尽管站点的功能需要能够上载文件,但将它们存储在URL无法直接访问的目录中会使得更难以利用它们。 同样,使用脚本来服务它们而不是Web服务器的MIME处理程序可以确保将图像视为数据流而不是可执行文件。

这种安全性是否荒谬取决于用户数量,收集的数据的性质以及网站的微不足道。 至少,攻击者希望获得用户的密码,因为他们倾向于同步它们。 您网站上的密码为ABC123的用户可能会将相同的密码用于电子邮件,社交网站以及可能的银行和金融网站。 除了密码之外,如果您收集的有关您的用户的数据是个人身份识别或具有其他市场价值,或者您只是拥有大量用户,那么您必须假设该网站将成为目标。 这意味着,要么更谨慎地提供用户提供的图像文件,要么非常好地验证它们,要么两者兼而有之。

我对使用imagemagick是否能解决安全问题没有一个好的答案。 至少,请务必使用当前版本,因为快速搜索会发现许多已知漏洞。 请记住,您需要担心的文件可能会破坏图像效果,即使它们没有利用其中一个已知漏洞,所以一定要有非常好的错误捕获。

如果图像是非私有的,即你可以很容易地看到它们,你只是不想让别人随意阅读它们,给每个人一个唯一的名字就足够了。

如果有超过几千(并且似乎可能),那么创建存储它们的目录层次结构也可以帮助加快访问速度,同时增加搜索空间以至于无法通过随机搜索找到它们。 例如:名为347168a5d9b4ac5eb386e396f68b2231.jpg的文件可以放入目录:/images/34/71/68/347168a5d9b4ac5eb386e396f68b2231.jpg多级目录通过避免扫描数千个目录条目和随机名称来加快访问速度(存储在附加到用户图库中图像列表的数据库中)可以阻止查找随机文件。

这样一个脚本的开销听起来很荒谬。

同样在这里。 如果图像可公开访问,我绝对没有理由这样做。

如果它们不可公开访问(即只能由登录用户访问),那么就没有办法解决您的同事描述的方式(或者在执行登录检查后使用X-Sendfile ,这样可以节省部分开销)必要的软件安装)。 但如果情况并非如此,那么所需的开销就是疯狂的

如果你确定你确实需要图片是安全的,那么这就是我在漫画项目中使用的内容(基本上我把大量的漫画放在一个目录中,然后当有一些时间点击时,我允许访问它们一次一个)

//check if image should be accessed by the current request...

$fh=fopen($my_image,"rb");

if($fh==NULL){
        exit();
}
rewind($fh);
header("Content-Type: image/png");
header("Content-Length: " . filesize($fn));
fpassthru($fh);

fclose($fh);
exit();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM