【问题标题】:PHP image uploads. how do I protect against images containning code?PHP 图片上传。如何防止包含代码的图像?
【发布时间】:2011-05-23 19:10:29
【问题描述】:

据我了解,图像(jpeg、gif 等)可能包含有效的 php/python/perl 等代码。所以 - 任何人都可以创建有效的 jpeg 文件,同时可以由 PHP 解释器执行。 (这里是描述:link

所以 - 我想知道 - 有没有办法从图像中去除恶意代码?用 GD 或 imagemagic 重新编码图像会起作用吗?

谢谢!

【问题讨论】:

  • 在存在用户上传文件的目录中简单地阻止PHP等的执行可能会更好。
  • 是的。谢谢。我正在这样做,而且已经做得更多了。但是在服务器上不要有任何恶意代码似乎仍然很有帮助,以防万一以后有服务器切换/升级或其他管理服务器的人不知道这一点。

标签: php file-upload


【解决方案1】:

实际图片不包含代码。但是没有什么能阻止某人尝试上传“图像”文件,然后尝试让它执行。

您的解释器(Perl、PHP 等)应设置为只执行某些文件类型(即 .php 或 .php5)。没有理由 Perl 或 PHP 应该解析图像文件。

只需使用以下常识来保护自己:

1) 验证文档的 MIME 类型
2) 执行只允许上传特定扩展名文件的政策
3) 不要接受表面价值的文件名。生成您自己的内部文件名并使用数据库表来保存映射。
4) 如果你真的很偏执,找一些代码来检查字节签名对于给定的文件类型上传是否有效。

【讨论】:

  • 1) 由客户端设置 - 很容易被欺骗 2) 即使我们现在确切知道 PHP 解释了哪些文件扩展名,我们也不能保证这在将来的某个时候不会改变,当Web 服务器上安装了一些其他应用程序。到那时,每个人都一定会忘记我们服务器的安全性取决于此设置。 3) 对 SEO 也不利 - 还会有更高的数据库负载 - 如果我需要一个图像 url 来发送电子邮件或其他东西怎么办 4) 我确实将 file_info 与魔法数据库一起使用,所以我猜我很偏执,但是字节头仍然很容易被欺骗。
  • 好吧,反驳一下,1)我不是在谈论验证来自客户端的 mime 类型,而是使用库来分析实际文件; 2) PHP 不应该解析图像文件以将它们作为 PHP 代码执行; 3)同意这部分,但大多数允许上传图片的大型网站都做同​​样的事情;如果您需要链接,则为用户提供指向实际文件的链接;您不必使用他们的文件名(确实不应该在发生冲突的情况下使用);并且写到#4,你应该总是在实际文件上执行你的分析服务器端,它不能被欺骗。
  • 好吧。当用户上传文件时 - 浏览器(或 swf/java 插件)会根据文件提交 mime 信息。这就是 $_FILES["File"]["type"] 中显示的内容,并且可以被欺骗。如果您在服务器端验证 mime 类型 - 这通常通过使用魔法数据库和 finfo_file 函数来完成 - 这会更可靠一些,但仍然没有人阻止攻击者在上传文件之前添加错误的字节头。所以 - 回想起来 - 如果你的意思是你的 1) 应该在服务器端完成 - 那么你的 1) 和 4) 是一样的。
  • @Andre:这是绝对正确的,MIME 类型甚至魔术字节都可以被欺骗。问题是这是否是攻击的威胁媒介。如果您允许用户上传内容,则没有 100% 确定的方式来限制某人将上传的内容。但是考虑到标准的服务器强化实践,你不应该执行任何用户上传的内容,你不应该允许用户上传 php/perl/executable 文件。除非您亲自检查上传的每个文件,否则无法完全阻止它,这是不切实际的。
【解决方案2】:

您应该配置您的网络服务器,不允许您的图像文件扩展名被 PHP 解释。如问题中链接的页面所示,图像可以包含 PHP 代码。始终根据白名单检查文件扩展名:

<?php  
$whitelist = '/\.(?:jpe?g|png|gif)$/i'; 
if (!preg_match($whitelist, $_FILES['userfile']['name'])) {  
    echo "Bad filename extension.";  
    exit;  
}
$uploaddir = 'uploads/';  
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);  
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {  
    echo "File is valid, and was successfully uploaded.";  
} else {  
    echo "File uploading failed.";  
}  
?>

【讨论】:

  • 上传文件名中的扩展名很容易被绕过,最好使用getimagesize()函数,根据实际文件内容返回图片的真实mime类型。
  • 推荐的检测mime类型的方法是使用PHP的finfo函数。但这仍然是攻击者可以改变的。
猜你喜欢
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 2021-11-19
  • 1970-01-01
  • 2012-05-18
  • 2011-01-03
相关资源
最近更新 更多