验证文件的扩展名足以知道该文件没有隐藏病毒(或可以渗透到我的服务器的东西)吗?

Is verifying a file's extension enough to know that the file isn't hiding a virus (or something that can infiltrate my server)?

我正在开发一个用户可以上传“.docx”文件的系统。验证它的扩展名足以知道这个“.docx”文件没有被感染吗?

这是我的上传 PHP 代码:

<?php
session_start();

include("connection.php");
include("functions.php");

// Just to validate the user
$user_data = check_login($con);

include("connectionPostsDB.php");

if (isset($_POST['submit'])){

    $title = $_POST['title'];
    $tag = $_POST['tag'];
    $description = $_POST['description'];

    $file = $_FILES['file'];

    $fileName = $_FILES['file']['name'];
    $fileTmpName = $_FILES['file']['tmp_name'];
    $fileSize = $_FILES['file']['size'];
    $fileError = $_FILES['file']['error'];
    $fileType = $_FILES['file']['type'];

    $fileExt = explode('.', $fileName);
    $fileActualExt = strtolower(end($fileExt)); //here I get the actual file's extension (I hope xD)

    $allowed = array('docx');

    if(in_array($fileActualExt, $allowed)){
        if($fileError === 0){
            if($fileSize < 1000000){
                $fileNameNew = uniqid('', true).".".$fileActualExt;
                $fileDestination = '../imgs/posts/'.$fileNameNew;
                move_uploaded_file($fileTmpName, $fileDestination);

                $query = "INSERT INTO posts (title, descr, imgname, tag) 
                          VALUES ('".$title."','".$description."','".$fileNameNew."','".$tag."')";

                mysqli_query($postcon, $query);

                echo 'File successfully uploaded';
            }
            else {
                echo 'Your file is too big.';
            }
        }
        else {
            echo 'There was an error uploading your file.';
        }
    }
    else {
        echo 'This type of file not allowed.';
    }

}

那么,我检查文件的扩展名是否足以防止某些用户将某些 php 代码放入我的服务器(或执行某些操作以从服务器获取信息)?

不,仅仅检查文件扩展名是不够的,因为我们可以为任何文件类型设置 .docx 扩展名。

我们还应该检查更多内容,例如:

  1. 文件的 mime 类型是预期的吗?
  2. 文件大小是否足够合理。例如,如果有人上传了一个 25 GB 的 docx 文件,那么即使它是一个有效的 docx 文件,您的服务器也可能会崩溃。
  3. 理想情况下,您不应在任何生产服务器中上传任何文件,而应在任何存储提供商(如 AWS 的 s3 存储桶)中上传。因此,即使该文件是可执行文件,它也不会在您的服务器中执行。它被上传到另一个服务器,该服务器经过优化可以处理文件。

还有很多这样的事情需要考虑。

不,仅检查扩展名是不够的,但主要问题是您所说的 safe 的确切含义。

您显示的代码仅将文件存储在您的服务器上(在服务器生成的名称下),然后在数据库中发布它的存在。这些东西 本身 都不会有危险,即使该文件包含黑死病的数字等价物。

但是让我们先退一步;您的 SQL 查询非常 不安全 ,尽管这与上传的文件无关。当您以这种方式创建查询时,您应该阅读准备好的语句,因为您的整个网站都对 SQL 注入敞开大门。


现在,回到主题:

为了让 .docx 文件成为它应有的样子,您至少可以探索两件事。

  1. 据我所知,docx 格式实际上只是一个 .zip 文件,其中包含一些 .xml 文件。 PHP 理解这两种格式,因此您可以尝试解压缩它的内容,查看它是否包含您期望的文件类型,包括 xml(s),然后查看那些 XML文件是可解析的。

  2. 您可以将上传的文件提供给病毒扫描程序


这两种方法都不是完全证明,但它们都会稍微说明情况,让您(更具体地说,您的算法)做出更明智的决定。

现在说说我所说的“你所说的安全到底是什么意思”。您在此处执行的操作(仅重命名和存储文件以及将文本写入数据库)基本上是非常安全的。

但我想在该数据库的另一端,有人或其他东西读取同一个数据库 table,并允许某人打开和/或下载该文件。现在 该操作 实际上有很多安全隐患。

现在,如果该数据库只能通过您的应用程序查看,那么理论上您可以放弃所有责任并说“此文件是由上帝知道是谁匿名上传的,就好像它是由未知发件人到达您的电子邮件垃圾文件夹一样对待”。但是,如果您要承担任何级别的责任(无论是隐含的还是字面上的),您都必须在您满意的程度上对其进行验证table。