【问题标题】:Correct way to upload files in PHP Mailer在 PHP Mailer 中上传文件的正确方法
【发布时间】:2020-10-09 00:34:23
【问题描述】:

您好,有人可以帮助我使用这段代码来处理和测试我在 PHPMailer 中的文件上传吗?它基本上检查文件是否正确,然后使用用户名加上字段名和日期和时间重命名文件名。有多个文件,但我没有使用多上传器,而是使用单独的字段,以便我可以跟踪哪个文件是哪个。

脚本似乎可以工作,并且 php 错误日志中没有错误,但我被告知这是我上一篇文章中的一个安全漏洞,我的“pathinfo 调用应该测试实际文件的 tmp_name 的路径”而不是给定的原始名称。这是一个严重的安全漏洞。”

不幸的是,我不确定 pathinfo 的两种用法中的哪一种是错误的。如果我将 $file["name"] 更改为 $file["tmp_name"] for $imageFileExt 那么我没有得到文件扩展名,如果我将 $file["name"] 更改为 $file["tmp_name"] on $imageFileType 然后我得到了错误的文件错误。任何帮助将非常感激。谢谢。

    foreach ( $_FILES as $key => $file ) {
    
    //get the file extension
                $imageFileExt = strtolower( pathinfo( $file["name"], PATHINFO_EXTENSION ) );
    
//change the name of each file in $_FILES array to 
//the persons name plus file field plus date plus time plus file extension 
//such as :joe_bloggs_bank_statement_1_9_10_21_10_55.jpg
//and joe_bloggs_pay_slip_1_9_10_21_10_55.jpg
                $file['name'] = clean($_POST['appName']). "_" . $key . "_" . $dateKey . "." . $imageFileExt;
    
    // get the file type
                $target_file = $target_dir . basename($file["name"]);
                $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
    
    
    // get file size
                $check = getimagesize($file["tmp_name"]);
                if($check === false) {
                    $fileMessage .=  $key."=noimage,";
                    $uploadOk = 0;
                }
    
    // Allow certain file formats
    
            else if($imageFileType !== "jpg" && $imageFileType !== "png" && $imageFileType !== "jpeg"
                   && $imageFileType !== "gif" ) {
                    $fileMessage .=  $key."=wrongfile,";
                    $uploadOk = 0;
                }
    
    // Check if file already exists
            else if (file_exists($target_file)) {
                    $fileMessage .=  $key."=fileexists,";
                    $uploadOk = 0;
                }
    
    
    // Check file size
            else if ($file["size"] > 20000000) { //20mb
                    $fileMessage .=  $key."=toobig,";
                    $uploadOk = 0;
                }
    // creates a set of links to the uploaded files on the server 
    // to be placed in the body of the email (the files themselves do not get attached in the email
                $fileString .= strtoupper($key).": <a href='example.com/uploads/".$file['name']."'>".$file['name']."</a><br>";
    
    
            }

【问题讨论】:

    标签: php file-upload phpmailer


    【解决方案1】:

    我想你可能对这些东西之间的区别感到困惑。文件本身是用户提供的一堆字节。它的文件名是关于该文件的元数据,也由用户提供。 tmp_name 也是关于文件的元数据,但它是安全的,因为它不是由用户提供的。

    您绝不会使用move_uploaded_file()is_uploaded_file()。这些对于验证上传的文件是真正的上传文件是必要的,这些文件在运行脚本之前 已被 PHP 正确处理。这是您在信任 $_FILES 中的任何其他内容之前应该做的第一件事。

    不信任name 属性很重要的原因是文件名可以用作攻击媒介,例如通过包含路径遍历序列(例如../)、SQL 转义(')或如果在 shell 上下文(\&gt; 等)中使用可能会做意外事情的字符。 tmp_name 是 PHP 自己生成的,不包含用户提供的数据,不过你需要使用上面提到的函数来确保这是真实数据而不是注入 由用户。

    同样,不能依靠文件名准确地告诉您文件是什么类型 - 搜索“多语言文件”以了解为什么会出现问题。

    你没有显示你的 clean() 函数中的内容,所以我们不能说它的作用是否有效。

    在您之前的问题中,我将您推荐给the PHPMailer send file upload example。这显示了如何安全地处理上传。例如,它采用提供的任何名称并对其进行哈希处理,生成一个保证不受用户提供的数据安全的字符串。

    【讨论】:

    • 再次感谢您的回答,我确实尝试应用您之前给我的示例,但它使用了我不使用的多文件上传器,而是使用 9 个单独的文件上传器,它们都是必填字段。其次,我正在尝试遵循您在此处所说的内容并将其合并到我的代码中,但是我很难弄清楚代码中首先出现的内容。如果可以的话,我会尝试让它工作,然后在你面前运行该代码。我应该只编辑我原来的问题吗?
    • 好的,我想我已经成功了。我将创建一个新帖子,如果更好,我会将其标记为已回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 2011-01-08
    • 2019-07-13
    • 2011-04-08
    • 2016-02-26
    • 1970-01-01
    • 2014-10-23
    相关资源
    最近更新 更多