使用cURL上传文件到PHP

3

我目前正在尝试使用cURL可执行文件,使用POST方法将mp4文件上传到php脚本。在PHP文件中,我正在检查文件格式和所有这些类型的内容。以下是PHP文件:

<?php

$allowedExts = array("jpg", "jpeg", "gif", "png", "mp3", "mp4", "wma");
$extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);

if (($_FILES["file"]["type"] == "video/mp4") && ($_FILES["file"]["size"] < 2000000) && in_array($extension, $allowedExts)) {
    if ($_FILES["file"]["error"] > 0) {
        echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    } else {
        echo "Upload: " . $_FILES["file"]["name"] . "<br />";
        echo "Type: " . $_FILES["file"]["type"] . "<br />";
        echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
        echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

        if (file_exists("upload/" . $_FILES["file"]["name"])) {
            echo $_FILES["file"]["name"] . " already exists. ";
        } else {
            move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
            echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
        }
    }
} else {
    echo "Invalid file";
}
?>

当我使用普通的HTML表单上传文件时,它可以正常工作。下面是我使用的HTML表单:

<!DOCTYPE html>

<head>
    <title></title>
</head>

<body>

    <form action="upload_file.php" method="post" enctype="multipart/form-data" name="uploadedfile">
        <label for="file"><span>Filename:</span></label>
        <input type="file" name="file" id="file" /> 
        <br />
        <input type="submit" name="submit" value="Submit" />
    </form>
</body>
</html>

但是,当我使用cURL客户端尝试上传test.mp4文件时,使用以下命令:"curl -F file=@test.mp4 http://localhost:1337/upload_file.php",控制台显示“无效文件”,这通常是在PHP中检查文件类型属性不匹配时出现的错误提示。希望您能理解我的问题并能够帮助我! :) 问候 Steven

1
那么...你有进行过任何调试吗?在 if (($_FILES["file"]["type"] == "video/mp4") && ($_FILES["file"]["size"] < 2000000) && in_array($extension, $allowedExts)) 中的哪个条件失败了? - melpomene
这就是问题所在,通常情况下它们都不应该失败,因为当我通过HTML表单上传相同的文件时,它可以正常工作。 - Gee
2个回答

2

你的$_FILES["file"]["type"]检查失败是因为cURL不会猜测文件类型并自动在POST请求中发送。

这个检查很容易被欺骗,所以它并不是一个很好的检查方法。

但为了让你的示例起作用,请尝试使用文件参数指定内容类型:

curl -F file=@test.mp4;type=video/mp4 http://localhost:1337/upload_file.php

它起作用了,非常感谢! :)我可以问一下你所说的“容易欺骗”是什么意思吗?这是否意味着人们仍然可以在使用此脚本时上传非MP4文件到服务器? - Gee
1
由于没有对实际文件内容进行检查,我可以将PHP放入.mp4文件中,欺骗内容类型(就像我们在上面的cURL请求中所做的那样),并将其上传。但是,由于扩展名的原因,可能仍然无法将文件执行为PHP代码。 curl -F file = @test.mp4; type = whatever / i-want ... = 可以轻松欺骗。 - drew010
我刚做了一些研究,并通过 finfo_file($finfo, $_FILES["file"]["tmp_name"]) == "video/mp4" 添加了一个内容检查。如果我正确理解这个函数,那么现在人们只能上传mp4文件,对吗? 附注:$finfo = finfo_open(FILEINFO_MIME_TYPE); - Gee

1

在 drew010 所写的内容之后(我想写一条评论,但是还没有声望),信任传递的这些值可能实际上是一种安全风险,并且过去已经被用于黑客攻击网站,因此要小心。


谢谢您的提示,但是您是什么意思呢?这是否意味着人们仍然可以将非 mp4 文件上传到服务器? - Gee
1
好的,您可以检查文件扩展名来进行判断,但这也取决于操作系统或其他软件如何处理这些文件。我记得有一次将一个 PHP 文件上传为 image/png(因为允许上传 image/* 类型的文件),而且服务器还配置了支持将 PHP 脚本上传到 image 上传目录的功能(这种情况并不罕见)。 - Richard Thomas
1
但是为了回答你的问题,是的,人们将能够上传非mp4文件到服务器,因此您需要评估其中的风险。 - Richard Thomas
我刚做了一些研究,并通过 finfo_file($finfo, $_FILES["file"]["tmp_name"]) == "video/mp4" 添加了一个内容检查。如果我正确理解这个函数,那么现在人们只能上传mp4文件,对吗?附注:$finfo = finfo_open(FILEINFO_MIME_TYPE); - Gee
我会放心依赖它。尽管攻击者总是想出新的漏洞利用方式。最好的方法是转码视频,但这可能不合适。 - Richard Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接