首页 文章

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

提问于
浏览
28

我有一个在我的网站上用PHP创建的上传表单,人们可以上传一个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!");
    }
}

谢谢,本 .

10 回答

  • 1

    那你应该不仅仅依赖于文件扩展名 . 尝试通过图像库传递每个文件,以验证它真的是一个图像 .

  • 2

    我真的很担心人们能够上传恶意的php文件,安全隐患很大!

    冰山一角!

    我还需要注意人们改变php文件的扩展名,试图绕过这个安全功能 .

    通常,更改扩展名将阻止PHP将这些文件解释为脚本 . 但这不是唯一的问题 . 除了'...... php'之外还有更多可能会损害服务器端的东西; '.htaccess'和设置了X位的文件是显而易见的,但绝不是你要担心的 . 即使忽略服务器端的东西,也存在巨大的客户端问题 .

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

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

    此外,还可以制作一个文件既可以是您的图像解析器可以接受的有效图像,也可以包含嵌入式HTML . 根据用户浏览器的确切版本和图像文件的确切格式,有各种可能的结果(特别是JPEG具有非常可变的一组可能的 Headers 格式) . IE8中有mitigations,但是's no use for now, and you have to wonder why they can'只是's no use for now, and you have to wonder why they can'而不是让我们对HTTP标头的非标准扩展负担,这些扩展应该首先应该使用Just Worked .

    我又陷入了咆哮 . 我会停下来安全地提供用户提供的图像的策略:

    1:切勿使用从用户输入获取的文件名将文件存储在服务器的文件系统中 . 这可以防止错误和攻击:不同的文件系统对文件名中允许的字符有不同的规则,并且比你想象的“清理”文件名要困难得多 .

    即使您采取了非常严格的限制,例如“只有ASCII字母”,您仍然需要担心太长,太短和保留的名称:尝试保存一个名称与“com.txt”无关的文件Windows服务器并观看您的应用程序 . 您是否知道应用程序可能运行的每个文件系统的路径名称的所有奇怪缺陷?信心?

    而是在数据库中存储文件详细信息(例如名称和媒体类型),并在文件存储中使用主键作为名称(例如“74293.dat”) . 然后,您需要一种方法来为它们提供不同的明显文件名,例如下载文件的下载程序脚本,执行Web服务器内部重定向的下载程序脚本或URL重写 .

    2:使用ZipArchive非常非常小心 . 在相同类型的extractTo中存在遍历vulnerabilities,它影响了大多数天真的基于路径的ZIP提取器 . 此外,你打算从ZIP bombs开始攻击 . 最好避免任何不良文件名的危险,通过逐步浏览存档中的每个文件条目(例如,使用zip_read/zip_entry_*)并在手动将其流解压缩到具有已知良好名称和模式标志的文件之前检查其详细信息,而不是档案的帮助 . 忽略ZIP中的文件夹路径 .

    3:如果您可以加载图像文件并将其再次保存,特别是如果您以某种方式处理它(例如调整大小/缩略图或添加水印),您可以合理地确定结果将是清洁 . 从理论上说也许有可能制作一个针对特定图像压缩器的图像,这样当它被压缩时,结果看起来也像HTML,但这对我来说似乎是一次非常困难的攻击 .

    4:如果您可以将所有图像作为下载提供(即在下载程序脚本中使用“内容处理:附件”),那么您可能很安全 . 但这可能给用户带来太多不便 . 这可以与(3)协同工作,但是,在线提供较小的处理图像,并且仅提供原始的高质量图像作为下载 .

    5:如果您必须内联提供未经更改的图像,则可以通过从其他域提供服务来消除跨站点脚本风险 . 例如,对于不受信任的图像使用'images.example.com',对于包含所有逻辑的主站点使用'www.example.com' . 确保cookie仅限于正确的虚拟主机,并且虚拟主机已设置为无法响应除其正确名称之外的任何内容(另请参阅:DNS重新绑定攻击) . 这是许多webmail服务的功能 .

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

    总结,AAAARRRRRRRGGGGHHH .

    ETA评论:

    在顶部你提到'有X位设置的文件',你的意思是什么?

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

    我认为.htaccess必须在主根目录中,是不是这样?

    取决于Apache的设置方式,特别是AllowOverride指令 . 通用主机通常在任何目录上使用AllowOverride .

    如果有人仍然上传像./var/www/wr_dir/evil.php这样的文件,会发生什么?

    我希望领先的'..'将被丢弃,这就是遭受同样漏洞的其他工具所做的 .

    但我仍然不相信 extractTo() 反对恶意输入,有太多奇怪的小文件名/目录树的东西可能出错 - 特别是如果你期望永远在Windows服务器上运行 . zip_read() 使您可以更好地控制解密过程,因此攻击者更少 .

  • 0

    首先,您应该禁止每个没有正确图像文件扩展名的文件 . 之后,您可以使用getimagesize function来检查文件是否是常规图像文件 .

    但此外,您应该知道某些图像格式允许注释和其他元信息 . 这可以用于恶意代码,例如某些浏览器在某些情况下将执行的JavaScript(请参阅Risky MIME sniffing in Internet Explorer) .

  • 1

    我没有看到在你的数据库中重命名php文件的风险......只要你不将它们作为PHP文件进行评估(或者根本就没有),它们就不会造成太大的伤害,并且由于没有.php扩展名,因此php引擎不会触及它们 .

    我想你也可以搜索文件 <?php ...

    Also :假设上传到您计算机的文件最糟糕 . 重命名了're saving them 1396160 and treat it accordingly. Don' t使其公开的文件夹,不提供任何文件启动权限(特别是php用户)等 .

  • 0

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

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

  • 63

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

    offtopic:不要让用户选择几张图片而不是上传一个zip文件 . 对于那些不知道拉链是什么的人来说更好(是的,它们存在)

  • 1

    如果你将php设置为仅解析以.php结尾的文件,那么你可以将文件从somename.php重命名为somename.php.jpeg并且你是安全的 .

    如果你真的想要删除这些文件,那么php有一个zip library可用 . 您可以使用它来检查zip存档中所有文件的名称和扩展名上传,如果它包含一个php文件,给用户一个错误信息 .

  • 15

    就个人而言,我会在Apache配置中添加一些内容,以确保它从文件上传到的位置将PHP文件作为文本提供,因此您可以安全地使用,并且可以允许将来上载其他文件类型 .

  • 2

    要小心这个 Passing Malicious PHP Through getimagesize()

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

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

    更好地为您的用户徽标使用Stackoverflow使用的gravatar;)

  • 9

    使用getimagesize功能 . 完整程序: - 1.)提取图像/上传文件的扩展名,然后将扩展名与允许的扩展名进行比较 . 2.)现在创建一个随机字符串,用于重命名上传的文件 . 最好的想法是 md5(session_id().microtime()) . 它不能重复,如果您的服务器非常快,并且处理时间不到一微秒,则使用递增变量并使用字符串添加它们 . 现在移动该文件 .

    A tip 在上传目录中禁用PHP文件处理,它将始终阻止您受到任何服务器端攻击,如果可能的话,在根目录或httpd配置文件中添加您的htaccess并从那里禁用htaccess文件,它现在解决了您的最大问题

相关问题