【问题标题】:How do I serve user uploaded images?如何提供用户上传的图片?
【发布时间】:2012-05-31 18:04:08
【问题描述】:

我正在构建一个允许登录用户上传产品图片的小型网络应用程序。我正在尝试正确构建,并且在过去一些天真的实现之后,决定将所有上传的内容添加到我的公共文件夹中。

\app (public folder)
-\index.php
\includes
\config
\uploads

如果恶意用户设法上传 PHP 文件,服务器将无法访问或提供该文件。

话虽如此,我将如何在网页上提供这些图片?做这个的最好方式是什么?在过去,我使用了一个 getImage.php 文件,该文件将采用一个 ID 参数(以及一些生成值的哈希值以避免用户只是猜测 ID),它看起来像“getImage.php?id=555&c=44j54k3h5”。服务端抓取DB中的图片信息(真实路径)并加载内容,重建header,发送图片。

此方法是否存在任何安全问题?有没有办法让它更漂亮?有一个查找 /images/imagename.jpg 并将它们发送到我的 getImage.php 文件的 htaccess 重写规则会添加安全漏洞吗?任何关于最佳实践的建议都将不胜感激。

【问题讨论】:

  • 您在上传文件时对文件进行了哪些类型的安全检查?
  • 好吧,我还没有构建它,我想先确保我没有忽略一些巨大的步骤。我将检查扩展,并从那里通过使用 getimagesize() 查找它们的尺寸来确保它们是图像,因为这似乎是一种常见的方法......够了吗?
  • getimagesize() 相当慢,检查文件扩展名并不是万无一失的。我使用一个图像上传类来检查大量不同的东西以确保文件不是恶意软件。让我看看能不能找到...

标签: php file-upload


【解决方案1】:

看看这个课程。它将处理上传,进行安全检查并为您煮咖啡:)

http://www.verot.net/php_class_upload.htm

【讨论】:

    【解决方案2】:

    提供上传图片的方法的安全性确实取决于许多其他因素。

    • 上传时如何处理和保护图像/文件?什么是 上传的目录/文件权限?
    • 哪些进程有权读取和写入这些位置?
    • 您有哪些类型的文件处理程序可以执行任意文件?
    • 如果您使用 PHP->get_image->display_image 路由,它是否会尝试在上传后阻止恶意意图(在 getimage 上?)

    我会使用Apache mod_alias 来引用webroot 上面的目录。这样,您仍然可以使用指向图像的链接,而无需打开完整的以上根目录进行曝光。

    【讨论】:

    • 谢谢,这些都是我会调查的。我计划在上传文件夹中添加一个 htaccess 文件,该文件将所有 php 处理程序与其分离(以防止它们被执行),但所有其他的东西我有点不熟悉:)
    【解决方案3】:

    “更漂亮”的方法是使用.htaccess 重定向

    RewriteEngine On                                                                                                                                                                                                                                  
    RewriteBase /                                                                                                                      
    RewriteRule ^getImage/([0-9]+)/(.+)\.png$ getImage.php?id=$1&c=$2 [NC,L]
    

    然后在getImage.php

    if (isset($_GET['id']) && isset($_GET['c'])) {
    
        // set headers
        header("Content-Type: image/png");
    
        // cache control
        header("Cache-Control: private, max-age=10800, pre-check=10800");
        header("Pragma: private");
        header("Expires: " . date(DATE_RFC822, strtotime("2 day")));
        if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
                header('Last-Modified: ' . $_SERVER['HTTP_IF_MODIFIED_SINCE'], true, 304);                                    
                exit;                            
        }
    
        /* do things */
        imagepng($image_resource);
        imagedestroy($image_resource);
    }
    else {
    
        echo "bad request";
    }
    

    所以不是

    site.com/getImage.php?id=555&c=44j54k3h5
    

    你会使用

    site.com/getImage/555/44j54k3h5.png
    

    此方法不会增加任何安全风险或漏洞。只需确保在查询之前对 get 变量进行转义即可避免注入攻击。

    如果您想保护自己免受恶意文件上传的侵害,则需要在提供服务之前执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2014-11-24
      • 2022-12-19
      • 2017-02-07
      • 1970-01-01
      • 2012-07-05
      相关资源
      最近更新 更多