阻止人们通过表单上传恶意PHP文件

我有一个上传表单在我的网站上的PHP创build,人们可以上传一个zip文件。 然后提取zip文件,并将所有文件位置添加到数据库。 上传表单仅供人上传图片,显然这些文件在zip文件夹中,我无法检查文件是否被上传。 我需要一段代码,将删除所有非图像格式(.png,.jpeg等)的文件。 我真的很担心人们能够上传恶意的php文件,很大的安全风险! 我还需要知道人们正在改变PHP文件的扩展名,试图绕过这个安全特性。

这是我使用的原始脚本http://net.tutsplus.com/videos/screencasts/how-to-open-zip-files-with-php/

这是实际提取.zip文件的代码:

function openZip($file_to_open) { global $target; $zip = new ZipArchive(); $x = $zip->open($file_to_open); if($x === true) { $zip->extractTo($target); $zip->close(); unlink($file_to_open); } else { die("There was a problem. Please try again!"); } } 

谢谢,本。

我真的担心人们能够上传恶意的PHP文件,很大的安全风险!

冰山一angular!

我也需要知道人们改变PHP文件的扩展,试图绕过这个安全function。

通常更改扩展将阻止PHP将这些文件解释为脚本。 但这不是唯一的问题。 有更多的东西比'… PHP',可以破坏服务器端; “.htaccess”和X位设置的文件是显而易见的,但绝不是所有人都必须担心的。 即使忽略服务器端的东西,也有一个巨大的客户端问题。

例如,如果有人可以上传“.html”文件,他们可以在其中包含一个<script>标记,劫持第三方用户的会话,并删除所有上传的文件或更改密码。 这是一个经典的跨站点脚本(XSS)攻击。

此外,由于某些浏览器(主要是IE)的“内容嗅探”行为,上传为“.gif”的文件实际上可能包含这种恶意HTML。 如果IE在文件开头附近看到类似(但不限于)“<html>”的信息,它可以忽略服务的“Content-Type”并显示为HTML,从而产生XSS。

另外,可以创build一个文件,这个文件既是图像parsing器可以接受的有效图像, 包含embedded的HTML。 根据用户的浏览器的确切版本和图像文件的确切格式(特别是JPEG具有非常可变的头部格式集合),存在各种可能的结果。 IE8有一些缓解措施 ,但现在没有用,你不得不想知道为什么他们不能简单地停止做内容嗅探,你是白痴MS,而不是给我们带来那些应该有HTTP标头的简单的非标准扩展刚开始工作。

我又一次咆哮起来。 我会停下来 安全地提供用户提供的图像的策略:

1:不要使用从用户input中获取的文件名将文件存储在服务器的文件系统上。 这可以防止错误以及攻击:不同的文件系统对文件名中允许使用哪些字符有不同的规则,而且比您想象的“清理”文件名要困难得多。

即使你采取了像“只有ASCII字母”的限制性的东西,你仍然需要担心太长,太短和保留的名字:尝试保存一个名为“com.txt”的无害的文件Windows服务器,看你的应用程序下降。 想想你知道你的应用程序可能运行的每个文件系统的path名的所有奇怪的弱点? 信心?

相反,将文件详细信息(如名称和介质types)存储在数据库中,并将主键用作文件存储库中的名称(例如“74293.dat”)。 然后,您需要一种方式来为它们提供不同的明显文件名,例如将文件分发出去的下载器脚本,执行Web服务器内部redirect的下载器脚本或URL重写。

2:使用ZipArchive非常小心。 在同样types的extractTo中存在遍历漏洞 ,这些漏洞已经影响了大多数幼稚的基于path的ZIP提取器。 另外,你自己打开受到来自ZIP炸弹的攻击。 最好避免出现文件名不好的危险,通过遍历文件中的每个文件条目(例如使用zip_read / zip_entry_ * )并检查其详细信息,然后手动将其stream解包到具有已知好名称和模式标志的文件,生成没有存档的帮助。 忽略ZIP中的文件夹path。

3:如果您可以加载图像文件并将其保存回来 ,特别是如果您以某种方式处理图像文件(例如resize/缩略图或添加水印),则可以合理确定结果是清洁。 从理论上讲,可以制作一个针对特定图像压缩器的图像,这样在压缩时,结果也会看起来像HTML,但这对我来说似乎是一个非常困难的攻击。

4:如果您可以放弃将所有图片作为下载(即在下载程序脚本中使用“内容处置:附件”),则可能是安全的。 但这对用户来说可能太不方便了。 这可以与(3)一起使用,但是,内嵌较小的处理过的图像并且只有下载才具有原始的高质量图像。

5:如果您必须以内联方式提供未经更改的图像,则可以通过在不同域中提供跨站点脚本风险来消除这种风险。 例如,对于不受信任的图像使用“images.example.com”,对于拥有所有逻辑的主站点使用“www.example.com”。 请确保cookie仅限于正确的虚拟主机,并且虚拟主机已设置为不能响应任何内容而不是其专有名称(另请参阅:DNS重新绑定攻击)。 这是许多networking邮件服务所做的。

总之,用户提交的媒体内容是一个问题。

总结总结,AAAARRRRRRRGGGGHHH。

ETA重新评论:

在上面提到的“X位设置的文件”,你是什么意思?

我不能说为ZipArchive.extractTo()因为我没有testing它,但许多提取器,当要求转储文件的档案,将重新创build[一些]与每个文件相关的Unix文件模式标志(如果档案是在Unix上创build的,所以实际上有模式标志)。 如果所有者读取权限丢失,这可能会导致您的权限问题。 但是,如果你的服务器启用了CGI,它也可能是一个安全问题:一个X位可以让文件被解释为一个脚本,并传递给第一行hashbang中列出的任何脚本解释器。

我以为.htaccess必须在主要的根目录,是不是这样的情况?

取决于如何设置Apache,特别是AllowOverride指令。 一般用途的主机在任何目录下都可以使用AllowOverride。

如果有人还上传了像../var/www/wr_dir/evil.php这样的文件会怎么样?

我预计领先的'..'将被丢弃,这是遭受同样的漏洞已经做了其他工具。

但是我仍然不相信extractTo()对付恶意input,有太多奇怪的小文件名/目录树的东西可能会出错 – 特别是如果你期望永远在Windows服务器上运行。 zip_read()让您更好地控制zip_read()进程,因此攻击者更less。

首先,你应该禁止没有适当的图像文件扩展名的文件。 之后,您可以使用getimagesize函数来检查文件是否为常规图像文件。

但是,你应该知道,一些图像格式允许评论和其他元信息。 这可以用于某些浏览器在某些情况下执行的JavaScript等恶意代码(请参阅Internet Explorer中的危险MIME嗅探 )。

那么你可能不应该仅仅依靠文件扩展名。 尝试传递每个文件通过一个图像库来validation它真的是一个图像,也。

我没有看到重命名你的数据库中的PHP文件的风险…只要你不评估他们作为PHP文件(或根本就不是),他们不能做太多的伤害,因为没有.php扩展名,php引擎不会触及它们。

我想你也可以search<?php的文件…

另外 :假设上传到您的机器的文件最差。 将您保存的文件夹重命名为“病毒”,并对其进行相应处理。 不要公开,不要给任何文件启动权限(尤其是PHP用户)等。

您可能还想考虑使用以下库进行MIMEtypes检测:

http://ca.php.net/manual/en/ref.fileinfo.php

现在你依靠你的硬盘空间来提取。 您可以检查fileheaders以确定它们是什么types的文件。 有可能的图书馆。

offtopic:最好让用户select几个图像,而不是上传一个zip文件。 更好的人不知道什么邮编(是的,他们存在)

如果你设置php只parsing以.php结尾的文件,那么你可以重命名一个文件从somename.php到somename.php.jpeg,你是安全的。

如果你真的想删除文件,有一个zip库可用于PHP。 你可以使用它来检查上传的zip压缩文件中的所有文件的名称和扩展名,如果它包含一个php文件,给用户一个错误信息。

就我个人而言,我会在Apacheconfiguration文件中添加一些内容,以确保它将PHP文件作为文件从file upload到的位置提供,这样您就可以安全使用,并且可以允许其他文件types在将来上传。

通过getimagesize()来传递恶意PHP

通过使用getimagesize()函数尝试确保图像安全的图像函数注入PHP

在这里阅读更多http://ha.ckers.org/blog/20070604/passing-malicious-php-through-getimagesize/

更好的用户标识使用gravatar像这里使用的Stackoverflow;)

使用getimagesize函数。 完整程序: – 1.)提取图像/上传文件的扩展名,然后将扩展名与允许的扩展名进行比较。 2.)现在创build一个随机的string重命名上传的文件。 最好的想法是md5(session_id().microtime())它不能被复制,如果你的服务器速度非常快,可以处理less于一微秒比使用增量variables和添加string。 现在移动该文件。

一个提示禁用上传目录中的PHP文件处理,它将始终阻止你从任何服务器端的攻击,如果可能的话,添加你的htaccess在根目录或在httpdconfiguration文件,并从那里禁用htaccess文件,现在它解决您的最大问题